Example #1
0
 public static function act_save_item($term_id, $tt_id, $taxonomy)
 {
     if (!in_array($taxonomy, pp_get_enabled_taxonomies())) {
         if (!empty($_REQUEST['pp_enable_taxonomy'])) {
             $enabled_taxonomies = get_option('pp_enabled_taxonomies');
             $enabled_taxonomies[$taxonomy] = '1';
             update_option('pp_enabled_taxonomies', $enabled_taxonomies);
         }
         return;
     }
     static $saved_terms;
     if (!isset($saved_terms)) {
         $saved_terms = array();
     }
     // so this filter doesn't get called by hook AND internally
     if (isset($saved_terms[$taxonomy][$tt_id])) {
         return;
     }
     // parent settings can affect the auto-assignment of propagating exceptions
     $set_parent = is_taxonomy_hierarchical($taxonomy) && !empty($_REQUEST['parent']) ? (int) $_REQUEST['parent'] : 0;
     if ($set_parent < 0) {
         $set_parent = 0;
     }
     $saved_terms[$taxonomy][$tt_id] = 1;
     // Determine whether this object is new (first time this PP filter has run for it, though the object may already be inserted into db)
     $last_parent = 0;
     if (!($last_parents = get_option("pp_last_{$taxonomy}_parents"))) {
         $last_parents = array();
     }
     if (!isset($last_parents[$tt_id])) {
         $is_new = true;
         $last_parents = array();
     } else {
         $is_new = false;
     }
     if (isset($last_parents[$tt_id])) {
         $last_parent = $last_parents[$tt_id];
     }
     if ($set_parent != $last_parent && ($set_parent || $last_parent)) {
         $last_parents[$tt_id] = $set_parent;
         update_option("pp_last_{$taxonomy}_parents", $last_parents);
     }
     $exceptions_customized = false;
     if (!$is_new) {
         if ($custom_exc_objects = get_option("pp_custom_{$taxonomy}")) {
             $exceptions_customized = isset($custom_exc_objects[$tt_id]);
         }
     }
     global $typenow;
     require_once dirname(__FILE__) . '/item-save_pp.php';
     $args = compact('is_new', 'set_parent', 'last_parent', 'disallow_manual_entry');
     $args['via_item_type'] = $taxonomy;
     PP_ItemSave::item_update_process_exceptions('term', 'post', $tt_id, $args);
     do_action('pp_update_item_exceptions', 'term', $tt_id, $args);
 }
 function skip_filtering($taxonomies, $args)
 {
     if (!($taxonomies = array_intersect($taxonomies, pp_get_enabled_taxonomies()))) {
         return true;
     }
     if (!empty($args['pp_no_filter']) || $this->no_filter || apply_filters('pp_terms_skip_filtering', false, $taxonomies, $args)) {
         return true;
     }
     if ('id=>parent' == $args['fields']) {
         // internal storage of {$taxonomy}_children
         return true;
     }
 }
 function add_meta_boxes()
 {
     // ========= register WP-rendered metaboxes ============
     global $typenow;
     $taxonomy = isset($_REQUEST['taxonomy']) ? pp_sanitize_key($_REQUEST['taxonomy']) : '';
     if (!in_array($taxonomy, pp_get_enabled_taxonomies())) {
         return;
     }
     $tt_id = !empty($_REQUEST['tag_ID']) ? pp_termid_to_ttid((int) $_REQUEST['tag_ID'], $taxonomy) : 0;
     $post_type = !empty($_REQUEST['pp_universal']) ? '' : $typenow;
     $hidden_types = apply_filters('pp_hidden_post_types', array());
     $hidden_taxonomies = apply_filters('pp_hidden_taxonomies', array());
     if (!empty($hidden_taxonomies[$taxonomy]) || $post_type && !empty($hidden_types[$post_type])) {
         return;
     }
     //TODO: selectively enable role assignment by non-administrator
     if (!current_user_can('pp_assign_roles') || apply_filters('pp_disable_exception_ui', false, 'term', $tt_id, $post_type)) {
         return;
     }
     //if ( ! $this->_roles_editable( $src_name, $object_type ) )
     //	return;
     $tx = get_taxonomy($taxonomy);
     $type_obj = get_post_type_object($post_type);
     $register_type = $post_type ? $post_type : 'post';
     $ops = _pp_can_set_exceptions('read', $post_type, array('via_item_source' => 'term', 'via_item_type' => $taxonomy, 'for_item_source' => 'post')) ? array('read' => true) : array();
     $operations = apply_filters('pp_item_edit_exception_ops', $ops, 'post', $taxonomy, $post_type);
     $boxes = array();
     foreach (array_keys($operations) as $op) {
         if ($op_obj = pp_get_op_object($op, $post_type)) {
             if ('assign' == $op) {
                 $title = $post_type ? sprintf(__('%1$s %2$s %3$s Exceptions', 'pp'), $type_obj->labels->singular_name, $tx->labels->singular_name, $op_obj->noun_label) : sprintf(__('%1$s %2$s Exceptions (all post types)', 'pp'), $tx->labels->singular_name, $op_obj->noun_label);
             } elseif (in_array($op, array('read', 'edit'))) {
                 $title = $post_type ? sprintf(__('%1$s %2$s Exceptions (all post statuses)', 'pp'), $type_obj->labels->singular_name, $op_obj->noun_label) : sprintf(__('%1$s Exceptions (all post types, statuses)', 'pp'), $op_obj->noun_label);
             } else {
                 $title = $post_type ? sprintf(__('%1$s %2$s Exceptions', 'pp'), $type_obj->labels->singular_name, $op_obj->noun_label) : sprintf(__('%1$s Exceptions (all post types)', 'pp'), $op_obj->noun_label);
             }
             pp_set_array_elem($boxes, array($op, "pp_{$op}_{$post_type}_exceptions"));
             $boxes[$op]["pp_{$op}_{$post_type}_exceptions"]['for_item_type'] = $post_type;
             $boxes[$op]["pp_{$op}_{$post_type}_exceptions"]['title'] = $title;
         }
     }
     $boxes = apply_filters('pp_term_exceptions_metaboxes', $boxes, $taxonomy, $post_type);
     foreach ($boxes as $op => $boxes) {
         foreach ($boxes as $box_id => $_box) {
             // $screen = null, $context = 'advanced', $priority = 'default', $callback_args = null
             add_meta_box($box_id, $_box['title'], array(&$this, 'draw_exceptions_ui'), $register_type, 'normal', 'default', array('for_item_type' => $_box['for_item_type'], 'op' => $op));
         }
     }
 }
 function skip_filtering($taxonomies, $args)
 {
     if (!($taxonomies = array_intersect($taxonomies, pp_get_enabled_taxonomies()))) {
         return true;
     }
     if (!empty($args['pp_no_filter']) || $this->no_filter || apply_filters('pp_terms_skip_filtering', false, $taxonomies, $args)) {
         return true;
     }
     if ('id=>parent' == $args['fields']) {
         // internal storage of {$taxonomy}_children
         return true;
     }
     // Kriesi Enfold theme conflict on "More Posts" query
     if (defined('DOING_AJAX') && DOING_AJAX && in_array($_REQUEST['action'], apply_filters('pp_unfiltered_ajax_termcount', array('avia_ajax_masonry_more')))) {
         return true;
     }
 }
Example #5
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&amp;action=edit&amp;agent_id={$user->ID}&amp;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&amp;action=edit&agent_type=user&amp;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));
 }
</form>

<?php 
if (current_user_can('pp_assign_roles') && pp_bulk_roles_enabled()) {
    PP_GroupsUI::_draw_group_permissions($agent_id, $agent_type, $url, $wp_http_referer, compact('agent'));
}
if ('user' == $agent_type) {
    ?>
	<div>
	<?php 
    if ($agent_id) {
        $roles = array();
        $user = pp_get_user($agent_id);
        $user->retrieve_extra_groups();
        $post_types = pp_get_enabled_post_types(array(), 'object');
        $taxonomies = pp_get_enabled_taxonomies(array(), 'object');
        foreach (array_keys($user->groups) as $agent_type) {
            foreach (array_keys($user->groups[$agent_type]) as $_agent_id) {
                $args = compact($post_types, $taxonomies);
                $args['query_agent_ids'] = array_keys($user->groups[$agent_type]);
                $roles = array_merge($roles, ppc_get_roles($agent_type, $_agent_id, $args));
            }
        }
        require_once dirname(__FILE__) . '/profile_ui_pp.php';
        PP_ProfileUI::display_ui_user_groups(false, array('initial_hide' => true, 'selected_only' => true, 'force_display' => true, 'edit_membership_link' => true, 'hide_checkboxes' => true, 'user_id' => $agent_id));
        $role_group_caption = sprintf(__('Supplemental Roles %1$s(from primary role or %2$sgroup membership%3$s)%4$s', 'pp'), '<small>', "<a class='pp-show-groups' href='#'>", '</a>', '</small>');
        PP_GroupsUI::_current_roles_ui($roles, array('read_only' => true, 'class' => 'pp-group-roles', 'caption' => $role_group_caption));
        $exceptions = array();
        $args = array('assign_for' => '', 'inherited_from' => 0, 'extra_cols' => array('i.assign_for', 'i.eitem_id'), 'post_types' => array_keys($post_types), 'taxonomies' => array_keys($taxonomies), 'return_raw_results' => true);
        foreach (array_keys($user->groups) as $agent_type) {
            $args['agent_type'] = $agent_type;
Example #7
0
function _ppc_count_assigned_roles($agent_type, $args = array())
{
    global $wpdb;
    $defaults = array('query_agent_ids' => false, 'join_groups' => true);
    extract(array_merge($defaults, $args), EXTR_SKIP);
    $count = array();
    if ('user' == $agent_type && $join_groups) {
        $agent_clause = $query_agent_ids ? "AND gm.user_id IN ('" . implode("','", array_map('intval', (array) $query_agent_ids)) . "')" : '';
        $results = $wpdb->get_results("SELECT u.ID AS agent_id, r.role_name, COUNT(*) AS rolecount FROM {$wpdb->users} AS u INNER JOIN {$wpdb->pp_group_members} AS gm ON ( gm.user_id = u.ID {$agent_clause} ) INNER JOIN {$wpdb->ppc_roles} AS r ON ( ( r.agent_type = 'user' AND r.agent_id = gm.user_id ) OR ( r.agent_type = 'pp_group' AND r.agent_id = gm.group_id ) ) GROUP BY u.ID, r.role_name");
    } else {
        $agent_clause = $query_agent_ids ? "AND agent_id IN ('" . implode("','", array_map('intval', (array) $query_agent_ids)) . "')" : '';
        $results = $wpdb->get_results($wpdb->prepare("SELECT agent_id, role_name, COUNT(*) AS rolecount FROM {$wpdb->ppc_roles} WHERE agent_type = %s {$agent_clause} GROUP BY agent_id, role_name", $agent_type));
    }
    $item_types = array_merge(pp_get_enabled_post_types(), pp_get_enabled_taxonomies());
    foreach ($results as $row) {
        $arr_role = explode(':', $row->role_name);
        //$base_role_name = $arr_role[0];
        //$src_name = $arr_role[1];
        //$item_type = $arr_role[2];
        $no_ext = !defined('PPCE_VERSION') && !defined('PPS_VERSION');
        $no_custom_stati = !defined('PPS_VERSION');
        if (isset($arr_role[2]) && in_array($arr_role[2], $item_types)) {
            // roles for these post statuses will not be applied if corresponding extensions are inactive, so do not indicate in users/groups listing or profile
            if ($no_ext && strpos($row->role_name, ':post_status:') && !strpos($row->role_name, ':post_status:private')) {
                continue;
            } elseif ($no_custom_stati && strpos($row->role_name, ':post_status:') && !strpos($row->role_name, ':post_status:private') && !strpos($row->role_name, ':post_status:draft')) {
                continue;
            }
            if ($role_title = ppc_get_role_title($row->role_name, array('slug_fallback' => false))) {
                $count[$row->agent_id]['roles'][$role_title] = $row->rolecount;
                if (!isset($count[$row->agent_id]['role_count'])) {
                    $count[$row->agent_id]['role_count'] = 0;
                }
                $count[$row->agent_id]['role_count'] += $row->rolecount;
            }
        }
    }
    return $count;
}
 public static function get_exceptions($args = array())
 {
     $defaults = array('operations' => array(), 'inherited_from' => '', 'for_item_source' => false, 'via_item_source' => false, 'assign_for' => 'item', 'for_item_status' => false, 'post_types' => true, 'taxonomies' => true, 'item_id' => false, 'agent_type' => '', 'agent_id' => 0, 'query_agent_ids' => array(), 'ug_clause' => '', 'return_raw_results' => false, 'extra_cols' => array(), 'cols' => array());
     $args = array_merge($defaults, $args);
     extract($args, EXTR_SKIP);
     global $wpdb;
     $except = array();
     $operations = (array) $operations;
     if ($operations) {
         $operations = array_intersect($operations, pp_get_operations());
     } else {
         $operations = pp_get_operations();
     }
     if (!is_array($post_types)) {
         $post_types = pp_get_enabled_post_types();
     }
     if (!is_array($taxonomies)) {
         $taxonomies = pp_get_enabled_taxonomies();
     }
     $default_arr = array('include', 'exclude');
     if (!defined('PP_NO_ADDITIONAL_ACCESS')) {
         $default_arr[] = 'additional';
     }
     $valid_src_types = array('post' => array('post' => array('' => array_fill_keys($default_arr, array_fill_keys($post_types, array()))), 'term' => array()), 'term' => array('term' => array()), 'pp_group' => array('pp_group' => array()));
     if ($add_source_types = apply_filters('pp_add_exception_source_types', array())) {
         // valid return array is arr[for_item_source] = arr[via_item_src][via_item_type] = array('include', 'exclude' )
         $valid_src_types = array_merge($valid_src_types, $add_source_types);
     }
     if ($for_item_source) {
         $for_item_source = array_flip((array) $for_item_source);
         if (!($for_item_sources = array_intersect_key($for_item_source, $valid_src_types))) {
             return array();
         }
     } else {
         $for_item_sources = $valid_src_types;
     }
     $for_item_clauses = array();
     foreach (array_keys($for_item_sources) as $for_src_name) {
         if (isset($valid_src_types[$for_src_name])) {
             foreach ($operations as $op) {
                 $except["{$op}_{$for_src_name}"] = $valid_src_types[$for_src_name];
             }
             $for_types = array();
             foreach (array_keys($valid_src_types[$for_src_name]) as $via_src_name) {
                 if ('post' == $via_src_name) {
                     foreach (array_keys($valid_src_types[$for_src_name][$via_src_name]) as $via_type) {
                         foreach (array_keys($valid_src_types[$for_src_name][$via_src_name][$via_type]) as $mod_type) {
                             $for_types = array_merge($for_types, array_keys($valid_src_types[$for_src_name][$via_src_name][$via_type][$mod_type]));
                         }
                     }
                 } elseif ('term' == $via_src_name) {
                     if ('term' == $for_src_name) {
                         $for_types = $taxonomies;
                     } else {
                         $for_types = $post_types;
                     }
                 } else {
                     $for_types = false;
                 }
             }
             if (false === $for_types) {
                 $for_item_clauses[] = "e.for_item_source = '{$for_src_name}'";
             } else {
                 $for_item_clauses[] = "e.for_item_source = '{$for_src_name}' AND e.for_item_type IN ('', '" . implode("','", array_unique($for_types)) . "')";
             }
         }
     }
     if ($type_clause = pp_implode('OR', $for_item_clauses)) {
         $type_clause = "AND ( {$type_clause} )";
     }
     if ($via_item_source) {
         $type_clause .= $wpdb->prepare("AND e.via_item_source = '{$via_item_source}'", $via_item_source);
     }
     if ($agent_type && !$ug_clause) {
         $ug_clause = $wpdb->prepare(" AND e.agent_type = %s AND e.agent_id IN ('" . implode("','", array_map('intval', (array) $agent_id)) . "')", $agent_type);
     }
     $operation_clause = "AND e.operation IN ('" . implode("','", $operations) . "')";
     $mod_clause = defined('PP_NO_ADDITIONAL_ACCESS') ? "AND e.mod_type != 'additional'" : '';
     $assign_for_clause = $assign_for ? $wpdb->prepare("AND i.assign_for = %s", $assign_for) : '';
     $inherited_from_clause = $inherited_from !== '' ? $wpdb->prepare("AND i.inherited_from = %d", $inherited_from) : '';
     $status_clause = false !== $for_item_status ? $wpdb->prepare("AND e.for_item_status = %s", $for_item_status) : '';
     if (!$status_clause && !defined('PPS_VERSION')) {
         $status_clause = "AND e.for_item_status IN ('','post_status:private','post_status:draft')";
     }
     // exceptions for other statuses will not be applied correctly without custom statuses extension
     if (!$cols) {
         $cols = "e.operation, e.for_item_source, e.for_item_type, e.mod_type, e.via_item_source, e.via_item_type, e.for_item_status, i.item_id, i.assign_for";
     }
     $extra_cols_clause = $extra_cols ? ', ' . implode(",", $extra_cols) : '';
     $id_clause = false !== $item_id ? $wpdb->prepare("AND i.item_id = %d", $item_id) : '';
     $results = $wpdb->get_results("SELECT {$cols}{$extra_cols_clause} FROM {$wpdb->ppc_exceptions} AS e INNER JOIN {$wpdb->ppc_exception_items} AS i ON e.exception_id = i.exception_id WHERE ( 1=1 {$operation_clause} {$assign_for_clause} {$inherited_from_clause} {$mod_clause} {$type_clause} {$status_clause} {$id_clause} ) {$ug_clause}");
     if ($return_raw_results) {
         return $results;
     }
     foreach ($results as $row) {
         // note: currently only additional access can be status-specific
         $except["{$row->operation}_{$row->for_item_source}"][$row->via_item_source][$row->via_item_type][$row->mod_type][$row->for_item_type][$row->for_item_status][] = $row->item_id;
     }
     return $except;
 }
Example #9
0
 function get_exception_terms($operation, $mod_type, $post_type, $taxonomy, $args = array())
 {
     $status = isset($args['status']) ? $args['status'] : '';
     if ($post_type) {
         $for_item_src = post_type_exists($post_type) ? 'post' : 'term';
         if ('post' == $for_item_src && $taxonomy && !in_array($taxonomy, pp_get_enabled_taxonomies(array('object_type' => $post_type)))) {
             return array();
         }
     } else {
         $for_item_src = 'post';
     }
     // nullstring post_type means all post types
     if (!isset($this->except["{$operation}_{$for_item_src}"])) {
         $this->retrieve_exceptions($operation, $for_item_src);
     }
     $args['via_item_source'] = 'term';
     $args['via_item_type'] = $taxonomy;
     $args['status'] = true;
     // prevent filter from flattening exceptions array, since we will do it below
     $type_restricts = apply_filters('pp_get_exception_items', false, $operation, $mod_type, $post_type, $args);
     if (false === $type_restricts) {
         $type_restricts = isset($this->except["{$operation}_{$for_item_src}"]['term'][$taxonomy][$mod_type][$post_type]) ? $this->except["{$operation}_{$for_item_src}"]['term'][$taxonomy][$mod_type][$post_type] : array();
     }
     if ($post_type && !empty($args['merge_universals'])) {
         $universal_restricts = apply_filters('pp_get_exception_items', false, $operation, $mod_type, '', $args);
         if (false === $universal_restricts) {
             $universal_restricts = isset($this->except["{$operation}_{$for_item_src}"]['term'][$taxonomy][$mod_type]['']) ? $this->except["{$operation}_{$for_item_src}"]['term'][$taxonomy][$mod_type][''] : array();
         }
         foreach (array_keys($universal_restricts) as $_status) {
             pp_set_array_elem($type_restricts, array($_status));
             $type_restricts[$_status] = array_unique(array_merge($type_restricts[$_status], $universal_restricts[$_status]));
         }
     }
     if (!$type_restricts) {
         return array();
     }
     if (true === $status) {
         return $type_restricts;
     } else {
         $tt_ids = pp_array_flatten(array_intersect_key($type_restricts, array($status => true)));
     }
     if (!empty($args['return_term_ids'])) {
         return pp_ttid_to_termid($tt_ids, $taxonomy);
     } else {
         return array_unique($tt_ids);
     }
 }
 public static function add_term_restrictions_clause($required_operation, $post_type, $src_table, $args = array())
 {
     global $wpdb, $pp_current_user;
     extract(array_merge(array('merge_additions' => false, 'exempt_post_types' => array()), $args), EXTR_SKIP);
     $where = '';
     $excluded_ttids = array();
     $type_exemption_clause = $exempt_post_types ? " OR {$src_table}.post_type IN ('" . implode("','", $exempt_post_types) . "')" : '';
     $tx_args = $post_type ? array('object_type' => $post_type) : array();
     foreach (pp_get_enabled_taxonomies($tx_args) as $taxonomy) {
         $tx_additional_ids = $merge_additions ? $pp_current_user->get_exception_terms($required_operation, 'additional', $post_type, $taxonomy, array('status' => '', 'merge_universals' => true)) : array();
         // post may be required to be IN a term set for one taxonomy, and NOT IN a term set for another taxonomy
         foreach (array('include', 'exclude') as $mod) {
             if ($tt_ids = $pp_current_user->get_exception_terms($required_operation, $mod, $post_type, $taxonomy, $args)) {
                 if ('include' == $mod) {
                     if ($tx_additional_ids) {
                         $tt_ids = array_merge($tt_ids, $tx_additional_ids);
                     }
                     $term_include_clause = apply_filters('pp_term_include_clause', "{$src_table}.ID IN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ('" . implode("','", $tt_ids) . "') )", compact('tt_ids', 'src_table'));
                     $where .= " AND ( {$term_include_clause} {$type_exemption_clause} )";
                     continue 2;
                 } else {
                     if ($tx_additional_ids) {
                         $tt_ids = array_diff($tt_ids, $tx_additional_ids);
                     }
                     $excluded_ttids = array_merge($excluded_ttids, $tt_ids);
                 }
             }
         }
     }
     if ($excluded_ttids) {
         $where .= " AND ( {$src_table}.ID NOT IN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ('" . implode("','", $excluded_ttids) . "') ) {$type_exemption_clause} )";
     }
     return $where;
 }
 if (!is_user_logged_in()) {
     echo '<option>' . __('(login timed out)', 'pp') . '</option>';
     exit;
 }
 // TODO: deal with login timeout in JS to avoid multiple messages
 $types = array();
 if ('post' == $for_src_name) {
     if ('associate' != $operation) {
         if ('assign' != $operation) {
             // 'assign' op only pertains to terms
             if ($type_obj = get_post_type_object($for_type)) {
                 $types = array($for_type => __('selected:', 'pp'));
             }
         }
         $type_arg = $for_type ? array('object_type' => $for_type) : array();
         $taxonomies = pp_get_enabled_taxonomies($type_arg, 'object');
         if ($taxonomies) {
             $tax_types = array();
             foreach ($taxonomies as $_taxonomy => $tx) {
                 $tax_types[$_taxonomy] = $tx->labels->name;
             }
             uasort($tax_types, 'strnatcasecmp');
             // sort by values without resetting keys
             $types = array_merge($types, $tax_types);
         }
     } else {
         // 'associate' exceptions regulate parent assignment. This does not pertain to taxonomies, but may apply to other post types as specified by the filter.
         $aff_types = (array) apply_filters('pp_parent_types', array($for_type), $for_type);
         foreach ($aff_types as $_type) {
             if ($type_obj = get_post_type_object($_type)) {
                 $types[$_type] = $type_obj->labels->name;
 function flt_user_has_cap($wp_sitecaps, $orig_reqd_caps, $args)
 {
     if ($this->in_process || !isset($args[0])) {
         return $wp_sitecaps;
     }
     global $pp_current_user;
     if ($args[1] != $pp_current_user->ID) {
         return $wp_sitecaps;
     }
     //$args[0] = (array) $args[0];
     $args = (array) $args;
     $orig_cap = reset($args);
     if (isset($args[2])) {
         if (is_object($args[2])) {
             $args[2] = isset($args[2]->ID) ? $args[2]->ID : 0;
         }
     } else {
         $item_id = 0;
     }
     $item_id = isset($args[2]) ? $args[2] : 0;
     if ('read_document' == $orig_cap) {
         // todo: api
         $orig_cap = 'read_post';
     }
     if ('read_post' == $orig_cap && (count($orig_reqd_caps) > 1 || 'read' != reset($orig_reqd_caps))) {
         global $pp;
         if (!$pp->direct_file_access) {
             // deal with map_meta_cap() changing 'read_post' requirement to 'edit_post'
             $types = get_post_types(array('public' => true), 'object');
             foreach (array_keys($types) as $_post_type) {
                 if (array_intersect(array_intersect_key((array) $types[$_post_type]->cap, array_fill_keys(array('edit_posts', 'edit_others_posts', 'edit_published_posts', 'edit_private_posts'), true)), $orig_reqd_caps)) {
                     $orig_cap = 'edit_post';
                     break;
                 }
             }
         }
     }
     if (is_array($orig_cap) || !isset($this->meta_caps[$orig_cap])) {
         // Revisionary may pass array into args[0]
         // If we would fail a straight post cap check, pass it if appropriate additions stored
         if (array_diff($orig_reqd_caps, array_keys(array_intersect($wp_sitecaps, array(true, 1, '1'))))) {
             global $pp_cap_helper;
             $is_post_cap = false;
             $item_type = '';
             if ($type_caps = array_intersect($orig_reqd_caps, array_keys($pp_cap_helper->all_type_caps))) {
                 if (in_array($orig_cap, array_keys($this->meta_caps)) || in_array($orig_cap, array_keys($pp_cap_helper->all_type_caps))) {
                     $is_post_cap = true;
                     if (!$item_id && apply_filters('pp_do_find_post_id', true, $orig_reqd_caps, $args)) {
                         if ($item_id = pp_get_post_id()) {
                             $item_id = apply_filters('pp_get_post_id', $item_id, $orig_reqd_caps, $args);
                         }
                     }
                     // If a post id can be determined from url or POST, will check for exceptions on that post only
                     // Otherwise, credit basic read / edit_posts / delete_posts cap if corresponding addition is stored for any post/category of this type
                     if ($item_id) {
                         if ($_post = get_post($item_id)) {
                             $item_type = $_post->post_type;
                             $item_status = $_post->post_status;
                         }
                     } else {
                         $item_type = $this->post_type_from_caps($type_caps);
                         $item_status = '';
                     }
                     if ($item_type && !in_array($item_type, pp_get_enabled_post_types())) {
                         return $wp_sitecaps;
                     }
                 }
             }
             if ($params = apply_filters('pp_user_has_cap_params', array(), $orig_reqd_caps, compact('item_id', 'orig_cap', 'item_type'))) {
                 extract(array_diff_key($params, array_fill_keys(array('wp_sitecaps', 'pp_current_user', 'orig_cap', 'orig_reqd_caps'), true)));
                 // prevent some vars from being overwritten my extract
                 //if ( isset( $params['return_caps'] ) )
                 //	return $params['return_caps'];
             }
             if ($type_caps) {
                 static $buffer_qualified;
                 if (!isset($buffer_qualified) || $this->flags['memcache_disabled']) {
                     $buffer_qualified = array();
                 }
                 $bkey = $item_type . $item_id . md5(serialize($type_caps));
                 if (!empty($buffer_qualified[$bkey])) {
                     return array_merge($wp_sitecaps, array_fill_keys($orig_reqd_caps, true));
                 }
                 global $query_interceptor;
                 if ($is_post_cap && apply_filters('pp_use_post_exceptions', true, $item_type)) {
                     $pass = false;
                     $base_caps = $query_interceptor->get_base_caps($type_caps, $item_type);
                     /*
                     if ( ! $item_id && array_diff( $type_caps, $base_caps ) ) {
                     	return $wp_sitecaps;	// don't credit edit_others, edit_private, etc. based on addition stored for another post (this was needed due to previous failure to apply post_id passed into has_cap filter). But it is problematic for edit.php (display of Mine for lack of edit_others_posts)
                     }
                     */
                     if (count($base_caps) == 1) {
                         $base_cap = reset($base_caps);
                         switch ($base_cap) {
                             case 'read':
                                 $op = 'read';
                                 break;
                             default:
                                 $op = apply_filters('pp_cap_operation', false, $base_cap, $item_type);
                         }
                         if ($op) {
                             $_args = compact('item_type', 'orig_reqd_caps');
                             $valid_stati = apply_filters('pp_exception_stati', array_fill_keys(array('', "post_status:{$item_status}"), true), $item_status, $op, $_args);
                             $exc_post_type = apply_filters('pp_exception_post_type', $item_type, $op, $_args);
                             if ($additional_ids = $pp_current_user->get_exception_posts($op, 'additional', $exc_post_type, array('status' => true))) {
                                 $additional_ids = pp_array_flatten(array_intersect_key($additional_ids, $valid_stati));
                             }
                             if ($additional_ids) {
                                 $has_post_additions = apply_filters('pp_has_post_additions', null, $additional_ids, $item_type, $item_id, compact('op', 'orig_reqd_caps'));
                                 if (is_null($has_post_additions)) {
                                     $has_post_additions = !$item_id || in_array($item_id, $additional_ids);
                                 }
                             } else {
                                 $has_post_additions = false;
                             }
                             if ($has_post_additions) {
                                 $pass = true;
                             } else {
                                 if ($enabled_taxonomies = pp_get_enabled_taxonomies(array('object_type' => $item_type))) {
                                     global $wpdb;
                                     if (!$item_id || ($post_ttids = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_taxonomy_id = tr.term_taxonomy_id WHERE tt.taxonomy IN ('" . implode("','", $enabled_taxonomies) . "') AND tr.object_id = '{$item_id}'"))) {
                                         foreach (pp_get_enabled_taxonomies(array('object_type' => $item_type)) as $taxonomy) {
                                             if ($additional_tt_ids = $pp_current_user->get_exception_terms($op, 'additional', $item_type, $taxonomy, array('status' => true))) {
                                                 $additional_tt_ids = pp_array_flatten(array_intersect_key($additional_tt_ids, $valid_stati));
                                             }
                                             // merge in 'include' terms only if user has required caps in site-wide role
                                             if (!array_diff($orig_reqd_caps, array_intersect(array_keys($pp_current_user->allcaps), array(1, '1', true)))) {
                                                 if ($include_tt_ids = $pp_current_user->get_exception_terms($op, 'include', $item_type, $taxonomy, array('status' => true))) {
                                                     $additional_tt_ids = array_merge($additional_tt_ids, pp_array_flatten(array_intersect_key($include_tt_ids, $valid_stati)));
                                                 }
                                             }
                                             if ($additional_tt_ids) {
                                                 if (!$item_id || array_intersect($additional_tt_ids, $post_ttids)) {
                                                     $pass = true;
                                                     break;
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 } else {
                     if (!isset($params)) {
                         $params = apply_filters('pp_user_has_cap_params', array(), $orig_reqd_caps, compact('item_id', 'orig_cap', 'item_type'));
                     }
                     $pass = apply_filters('pp_credit_cap_exception', false, array_merge($params, compact('item_id')));
                 }
                 if ($pass) {
                     $buffer_qualified[$bkey] = true;
                     return array_merge($wp_sitecaps, array_fill_keys($orig_reqd_caps, true));
                 }
             }
         } else {
             if ($params = apply_filters('pp_user_has_cap_params', array(), $orig_reqd_caps, compact('item_id', 'orig_cap', 'item_type'))) {
                 if (empty($params['item_id'])) {
                     $params['item_id'] = $item_id ? $item_id : pp_get_post_id();
                 }
                 $wp_sitecaps = apply_filters('pp_user_has_caps', $wp_sitecaps, $orig_reqd_caps, $params);
                 extract(array_diff_key($params, array_fill_keys(array('wp_sitecaps', 'pp_current_user', 'orig_cap', 'orig_reqd_caps'), true)));
             }
         }
         return $wp_sitecaps;
     }
     $this->in_process = true;
     $this->args = $args;
     $src_name = isset($this->cap_data_sources[$orig_cap]) ? $this->cap_data_sources[$orig_cap] : 'post';
     switch ($src_name) {
         case 'post':
             if (!isset($required_operation)) {
                 $required_operation = $this->meta_caps[$orig_cap];
             }
             $return = $this->_flt_user_has_post_cap($wp_sitecaps, $orig_reqd_caps, $args, compact('required_operation'));
             break;
         default:
     }
     // end switch
     $this->in_process = false;
     $this->flags = $this->flag_defaults;
     return $return;
 }
Example #13
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
    }