Example #1
0
 function force_distinct_post_caps()
 {
     // but only if the post type has PP filtering enabled
     global $wp_post_types;
     $core_meta_caps = array_fill_keys(array('read_post', 'edit_post', 'delete_post'), true);
     $append_caps = array('edit_published_posts' => 'edit_posts', 'edit_private_posts' => 'edit_posts', 'delete_posts' => 'edit_posts', 'delete_others_posts' => 'delete_posts', 'delete_published_posts' => 'delete_posts', 'delete_private_posts' => 'delete_posts', 'read' => 'read');
     if ($force_create_posts_cap = pp_wp_ver('3.5-beta') && pp_get_option('define_create_posts_cap')) {
         foreach (array('post', 'page') as $post_type) {
             if ($force_create_posts_cap && $wp_post_types[$post_type]->cap->create_posts == $wp_post_types[$post_type]->cap->edit_posts) {
                 $wp_post_types[$post_type]->cap->create_posts = "create_{$post_type}s";
             }
         }
         $append_caps['create_posts'] = 'create_posts';
     }
     // post types which are enabled for PP filtering must have distinct type-related cap definitions
     foreach (pp_get_enabled_post_types() as $post_type) {
         // append missing capability definitions
         foreach ($append_caps as $prop => $default) {
             if (!isset($wp_post_types[$post_type]->cap->{$prop})) {
                 $wp_post_types[$post_type]->cap->{$prop} = 'read' == $prop ? 'read' : $wp_post_types[$post_type]->cap->{$default};
             }
         }
         $wp_post_types[$post_type]->map_meta_cap = true;
         $type_caps = array_diff_key((array) $wp_post_types[$post_type]->cap, $core_meta_caps);
         $cap_base = 'attachment' == $post_type ? 'file' : $post_type;
         foreach (array('post', 'page') as $generic_type) {
             if ($post_type != $generic_type) {
                 // page is not prevented from having 'page' cap defs, but IS prevented from having 'post' cap defs
                 // force distinct capability_type
                 if ($generic_type == $wp_post_types[$post_type]->capability_type) {
                     $wp_post_types[$post_type]->capability_type = $post_type;
                 }
                 // Replace "edit_posts" with "edit_doohickys". This is not ideal, but as of WP 3.4, no plural name is defined unless unless type-specific caps are already set.
                 // If this is a problem, just define the type caps in the register_post_type call, or modify existing $wp_post_types[$post_type]->cap values by hooking to the init action at priority 40.
                 //foreach( array_keys( array_intersect( (array) $wp_post_types[$generic_type]->cap, $type_caps ) ) as $cap_property ) {
                 foreach (array_keys($type_caps) as $cap_property) {
                     if (!in_array($type_caps[$cap_property], (array) $wp_post_types[$generic_type]->cap)) {
                         continue;
                     }
                     if ('create_posts' == $cap_property) {
                         $type_caps[$cap_property] = str_replace("_{$generic_type}", "_{$cap_base}", $wp_post_types[$generic_type]->cap->{$cap_property});
                     } else {
                         $type_caps[$cap_property] = str_replace("_{$generic_type}", "_{$cap_base}", $cap_property);
                     }
                 }
             }
         }
         $wp_post_types[$post_type]->cap = (object) array_merge((array) $wp_post_types[$post_type]->cap, $type_caps);
         $wp_post_types[$post_type]->plural_name = pp_plural_name_from_cap($wp_post_types[$post_type]);
         $this->all_type_caps = array_merge($this->all_type_caps, array_fill_keys($type_caps, true));
     }
     // end foreach post type
     // need this for casting to other types even if "post" type is not enabled for PP filtering
     $wp_post_types['post']->cap->set_posts_status = 'set_posts_status';
 }
Example #2
0
 public static function act_save_item($item_source, $post_id, $post)
 {
     if (!empty($_REQUEST['action']) && 'untrash' == $_REQUEST['action']) {
         return;
     }
     // WP always passes post object into do_action('save_post')
     if (!is_object($post)) {
         if (!($post = get_post($post_id))) {
             return;
         }
     }
     // operations in this function do not apply to revision save
     if ('revision' == $post->post_type) {
         return;
     }
     if (!in_array($post->post_type, pp_get_enabled_post_types())) {
         if (!empty($_REQUEST['pp_enable_post_type'])) {
             $enabled = get_option('pp_enabled_post_types');
             $enabled[$post->post_type] = '1';
             update_option('pp_enabled_post_types', $enabled);
         }
         return;
     }
     // don't execute this action handler more than one per post save
     static $saved_items;
     if (!isset($saved_items)) {
         $saved_items = array();
     }
     if (isset($saved_items[$post_id])) {
         return;
     }
     $saved_items[$post_id] = 1;
     $is_new = self::is_new_post($post_id, $post);
     if (is_post_type_hierarchical($post->post_type)) {
         $parent_info = self::get_post_parent_info($post_id, $post, true);
         extract($parent_info, EXTR_SKIP);
         // $set_parent, $last_parent
         if (is_numeric($last_parent)) {
             // not theoretically necessary, but an easy safeguard to avoid re-inheriting parent roles
             $is_new = false;
         }
     }
     if (empty($_REQUEST['page']) || 'rvy-revisions' != $_REQUEST['page']) {
         usleep(5000);
         // Work around intermittent failure to propagate exceptions.  Maybe storage of post row is delayed on some db servers.
         require_once dirname(__FILE__) . '/item-save_pp.php';
         PP_ItemSave::item_update_process_exceptions('post', 'post', $post_id, compact('is_new', 'set_parent', 'last_parent', 'disallow_manual_entry', 'via_item_type'));
     }
 }
Example #3
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));
 }
 public static function flt_comments_clauses($clauses, &$qry_obj, $args = array())
 {
     global $wpdb;
     $defaults = array('query_contexts' => array());
     extract(array_merge($defaults, $args), EXTR_SKIP);
     $query_contexts[] = 'comments';
     if (did_action('comment_post')) {
         // don't filter comment retrieval for email notification
         return $clauses;
     }
     if (is_admin() && defined('PP_NO_COMMENT_FILTERING')) {
         global $current_user;
         //if ( empty( $current_user->allcaps['moderate_comments'] ) )
         return $clauses;
     }
     if (empty($clauses['join']) || !strpos($clauses['join'], $wpdb->posts)) {
         $clauses['join'] .= " INNER JOIN {$wpdb->posts} ON {$wpdb->posts}.ID = {$wpdb->comments}.comment_post_ID";
     }
     // (subsequent filter will expand to additional statuses as appropriate)
     $clauses['where'] = preg_replace("/ post_status\\s*=\\s*[']?publish[']?/", " {$wpdb->posts}.post_status = 'publish'", $clauses['where']);
     $post_type = '';
     $post_id = !empty($qry_obj->query_vars['post_id']) ? $qry_obj->query_vars['post_id'] : 0;
     if ($post_id) {
         if ($_post = get_post($post_id)) {
             $post_type = $_post->post_type;
         }
     } else {
         $post_type = isset($qry_obj->query_vars['post_type']) ? $qry_obj->query_vars['post_type'] : '';
     }
     if ($post_type && !in_array($post_type, pp_get_enabled_post_types())) {
         return $clauses;
     }
     global $query_interceptor;
     $clauses['where'] = "1=1 " . $query_interceptor->flt_posts_where('AND ' . $clauses['where'], array('post_types' => $post_type, 'skip_teaser' => true, 'query_contexts' => $query_contexts));
     return $clauses;
 }
Example #5
0
 function act_prep_metaboxes()
 {
     global $pagenow;
     if ('edit.php' == $pagenow) {
         return;
     }
     static $been_here;
     if (isset($been_here)) {
         return;
     }
     $been_here = true;
     global $typenow;
     // pp_find_post_type();
     if (!in_array($typenow, pp_get_enabled_post_types()) || in_array($typenow, array('revision'))) {
         return;
     }
     //$can_admin_object = pp_is_user_administrator() || $pp_admin->user_can_admin_object('post', $object_id, $object_type);
     if (current_user_can('pp_assign_roles')) {
         $this->init_item_exceptions_ui();
         $args = array('post_types' => (array) $typenow, 'hierarchical' => is_post_type_hierarchical($typenow));
         // via_src, for_src, via_type, item_id, args
         $this->item_exceptions_ui->data->load_exceptions('post', 'post', $typenow, pp_get_post_id(), $args);
     }
 }
    function tx_enable_ui($tag)
    {
        global $taxonomy, $typenow;
        if ($typenow && !in_array($typenow, pp_get_enabled_post_types())) {
            return;
        }
        ?>
		<br /><br />
		<div id="poststuff" class="metabox-holder">
		<div id="post-body">
		<div id="post-body-content">
		<?php 
        require_once ABSPATH . 'wp-admin/includes/meta-boxes.php';
        add_meta_box("pp_enable_taxonomy", __('Press Permit Settings', 'pp'), array(&$this, 'draw_settings_ui'), $taxonomy, 'normal', 'default', array());
        do_meta_boxes($taxonomy, 'normal', $tag);
        ?>
		</div> <!-- post-body-content -->
		</div> <!-- post-body -->
		</div> <!-- poststuff -->
		<?php 
        echo '<div style="clear:both">&nbsp;</div>';
    }
</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) {
Example #8
0
 function __construct()
 {
     global $pagenow, $pp_plugin_page;
     do_action('_pp_admin_ui');
     // ============== UI-related filters ================
     add_action('admin_menu', array(&$this, 'build_menu'));
     add_action('show_user_profile', array(&$this, 'ui_user'), 2);
     add_action('edit_user_profile', array(&$this, 'ui_user'), 2);
     add_action('admin_print_scripts-user-new.php', array(&$this, 'insert_groups_ui'));
     add_action('admin_menu', array(&$this, 'ngg_uploader_workaround'));
     $is_post_admin = false;
     if (array_intersect(array($pagenow, $pp_plugin_page), array('post-new.php', 'post.php'))) {
         global $pp_post_edit_ui;
         require_once dirname(__FILE__) . '/post-edit-ui_pp.php';
         $pp_post_edit_ui = new PP_PostEditUI();
         $is_post_admin = true;
     } elseif ('edit-tags.php' == $pagenow && !empty($_REQUEST['action']) && 'edit' == $_REQUEST['action']) {
         if (current_user_can('pp_assign_roles')) {
             global $pp_term_edit_ui;
             require_once dirname(__FILE__) . '/term-edit-ui_pp.php';
             $pp_term_edit_ui = new PP_TermEditUI();
         }
     }
     if (pp_is_user_administrator() || 0 === strpos($pp_plugin_page, 'pp-')) {
         add_action('in_admin_footer', array(&$this, 'ui_admin_footer'));
     }
     if ('users.php' == $pagenow) {
         require_once dirname(__FILE__) . '/users-ui_pp.php';
     } elseif ('edit.php' == $pagenow || pp_is_ajax('inline-save')) {
         $post_type = isset($_REQUEST['post_type']) ? pp_sanitize_key($_REQUEST['post_type']) : 'post';
         if (in_array($post_type, pp_get_enabled_post_types())) {
             global $pp_post_listing_ui;
             require_once dirname(__FILE__) . '/post-listing-ui_pp.php';
             $pp_post_listing_ui = new PP_PostsAdmin();
             $is_post_admin = true;
         }
     } elseif (in_array($pagenow, array('edit-tags.php')) || defined('DOING_AJAX') && DOING_AJAX && isset($_REQUEST['action']) && in_array($_REQUEST['action'], array('inline-save-tax', 'add-tag'))) {
         if (!empty($_REQUEST['taxonomy']) && pp_is_taxonomy_enabled($_REQUEST['taxonomy'])) {
             global $pp_admin_terms_listing;
             require_once dirname(__FILE__) . '/term-listing-ui_pp.php';
             $pp_admin_terms_listing = new PP_TermsAdmin();
         }
     } elseif (in_array($pagenow, array('plugins.php', 'plugin-install.php'))) {
         global $pp_plugin_admin;
         require_once dirname(__FILE__) . '/admin-plugins_pp.php';
         $pp_plugin_admin = new PP_Plugin_Admin();
     } else {
         if (strpos($_SERVER['REQUEST_URI'], 'page=pp-groups') && isset($_REQUEST['wp_screen_options'])) {
             require_once dirname(__FILE__) . '/ui-helper_pp.php';
             PP_UI_Helper::handle_screen_options();
         }
         if (in_array($pp_plugin_page, array('pp-edit-permissions'))) {
             // pp-group-new
             add_action('admin_head', array(&$this, 'load_scripts'));
         } elseif (in_array($pp_plugin_page, array('pp-settings', 'pp-about'))) {
             wp_enqueue_style('plugin-install');
             wp_enqueue_script('plugin-install');
             add_thickbox();
         }
     }
     if ($is_post_admin) {
         do_action('pp_post_admin');
     }
     add_action('admin_head', array(&$this, 'admin_head'));
     wp_enqueue_style('pp', PP_URLPATH . '/admin/css/pp.css', array(), PPC_VERSION);
     if (0 === strpos($pp_plugin_page, 'pp-')) {
         wp_enqueue_style('pp-plugin-pages', PP_URLPATH . '/admin/css/pp-plugin-pages.css', array(), PPC_VERSION);
     }
     if (in_array($pagenow, array('user-edit.php', 'user-new.php', 'profile.php'))) {
         wp_enqueue_style('pp-edit-permissions', PP_URLPATH . '/admin/css/pp-edit-permissions.css', array(), PPC_VERSION);
         wp_enqueue_style('pp-groups-checklist', PP_URLPATH . '/admin/css/pp-groups-checklist.css', array(), PPC_VERSION);
         if (!pp_wp_ver('3.8')) {
             wp_enqueue_style('pp-edit-perm-legacy', PP_URLPATH . '/admin/css/pp-edit-permissions-legacy.css', array(), PPC_VERSION);
         }
     } elseif (in_array($pp_plugin_page, array('pp-edit-permissions', 'pp-group-new'))) {
         wp_enqueue_style('pp-edit-permissions', PP_URLPATH . '/admin/css/pp-edit-permissions.css', array(), PPC_VERSION);
         wp_enqueue_style('pp-groups-checklist', PP_URLPATH . '/admin/css/pp-groups-checklist.css', array(), PPC_VERSION);
         if (!pp_wp_ver('3.8')) {
             wp_enqueue_style('pp-edit-perm-legacy', PP_URLPATH . '/admin/css/pp-edit-permissions-legacy.css', array(), PPC_VERSION);
         }
     } elseif ('pp-settings' == $pp_plugin_page) {
         wp_enqueue_style('pp-settings', PP_URLPATH . '/admin/css/pp-settings.css', array(), PPC_VERSION);
     } elseif ('pp-about' == $pp_plugin_page) {
         wp_enqueue_style('pp-about', PP_URLPATH . '/admin/css/pp-about.css', array(), PPC_VERSION);
     }
     global $pagenow;
     if (in_array($pagenow, array('edit.php', 'post.php')) && pp_wp_ver('3.5-beta')) {
         add_action('admin_menu', array(&$this, 'reinstate_solo_submenus'));
         add_action('network_admin_menu', array(&$this, 'reinstate_solo_submenus'));
     }
     if (in_array($pagenow, array('edit.php', 'post.php', 'post-new.php', 'edit-tags.php', 'index.php')) || !empty($pp_plugin_page)) {
         add_action('admin_notices', array(&$this, 'admin_notice'));
     }
     do_action('pp_admin_ui');
 }
Example #9
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;
}
Example #10
0
function pp_get_enabled_taxonomies($args = array(), $output = 'names')
{
    $taxonomies = array();
    $orig_args = $args;
    if (isset($args['object_type'])) {
        $object_type = $args['object_type'];
        unset($args['object_type']);
    } else {
        $object_type = '';
    }
    $args['public'] = true;
    if (false === $object_type) {
        $taxonomies = get_taxonomies($args);
    } else {
        $object_types = $object_type ? (array) $object_type : pp_get_enabled_post_types();
        foreach (get_taxonomies($args, 'object') as $tx) {
            if (array_intersect($object_types, $tx->object_type)) {
                $taxonomies[] = $tx->name;
            }
        }
    }
    $taxonomies = pp_remove_disabled_taxonomies($taxonomies);
    $taxonomies = apply_filters('pp_enabled_taxonomies', $taxonomies, array_merge($args, $orig_args));
    if ('names' == $output) {
        return $taxonomies;
    }
    $arr = array();
    foreach ($taxonomies as $taxonomy) {
        $arr[$taxonomy] = get_taxonomy($taxonomy);
    }
    return $arr;
}
 function flt_terms_clauses($clauses, $taxonomies, $args)
 {
     if ($skip = $this->skip_filtering($taxonomies, $args)) {
         return $clauses;
     }
     global $pp_current_user;
     if ('all' == $args['fields'] || $args['hide_empty'] || $args['pad_counts']) {
         require_once dirname(__FILE__) . '/terms-interceptor-counts_pp.php';
         // adds get_terms filter to adjust post counts based on current user's access and pad_counts setting
         $clauses = PP_TermCountInterceptor::flt_terms_clauses($clauses, $args);
     }
     if (empty($args['required_operation'])) {
         $args['required_operation'] = apply_filters('pp_get_terms_operation', pp_is_front() ? 'read' : 'assign', $taxonomies, $args);
     }
     // must consider all related post types when filtering terms list
     // NOTE: If hide_empty is true, additional filtering will be applied to the results based on a full posts query.  Posts may have direct restrictions which make them inaccessable regardless of term restrictions.
     $all_excluded_ttids = array();
     $enabled_types = pp_get_enabled_post_types();
     $required_operation = $args['required_operation'];
     foreach ($taxonomies as $taxonomy) {
         $excluded_ttids = $included_ttids = array();
         $any_non_inclusions = false;
         if (!in_array($required_operation, array('manage', 'associate'))) {
             $universal = array();
             $universal['include'] = $pp_current_user->get_exception_terms($required_operation, 'include', '', $taxonomy);
             $universal['exclude'] = $universal['include'] ? array() : $pp_current_user->get_exception_terms($required_operation, 'exclude', '', $taxonomy);
             $universal['additional'] = $pp_current_user->get_exception_terms($required_operation, 'additional', '', $taxonomy);
             $universal = apply_filters('pp_get_terms_universal_exceptions', $universal, $required_operation, $taxonomy, $args);
             if (!empty($args['object_type'])) {
                 $exception_types = array_intersect((array) $args['object_type'], $enabled_types);
             } else {
                 $tx = get_taxonomy($taxonomy);
                 $exception_types = array_intersect((array) $tx->object_type, $enabled_types);
             }
         } else {
             $universal = array_fill_keys(array('include', 'exclude', 'additional'), array());
             $exception_types = array($taxonomy);
         }
         foreach ($exception_types as $post_type) {
             $additional_tt_ids = apply_filters('pp_get_terms_additional', array_merge($universal['additional'], $pp_current_user->get_exception_terms($required_operation, 'additional', $post_type, $taxonomy)), $required_operation, $post_type, $taxonomy, $args);
             foreach (array('include', 'exclude') as $mod_type) {
                 $args['additional_tt_ids'] = $additional_tt_ids;
                 $tt_ids = apply_filters('pp_get_terms_exceptions', $pp_current_user->get_exception_terms($required_operation, $mod_type, $post_type, $taxonomy), $required_operation, $mod_type, $post_type, $taxonomy, $args);
                 // remove type-specific inclusions from universal exclusions
                 if ('include' == $mod_type) {
                     $universal['exclude'] = array_diff($universal['exclude'], $tt_ids);
                 }
                 // merge type-specific exceptions with universal
                 if ($tt_ids = array_merge($universal[$mod_type], $tt_ids)) {
                     // add additional terms to includes set, and remove from exclude set (but only if include/exclude set exists to begin with)
                     if ($additional_tt_ids) {
                         $tt_ids = 'include' == $mod_type ? array_merge($tt_ids, $additional_tt_ids) : array_diff($tt_ids, $additional_tt_ids);
                     }
                 }
                 if ($tt_ids) {
                     if ('include' == $mod_type) {
                         $included_ttids = array_merge($included_ttids, $tt_ids);
                         if (count($exception_types) > 1) {
                             continue 2;
                         }
                         // don't support simultaneous include and exclude terms for the same taxonomy (but do support term assign exclusion even if an edit inclusion is set for the same term)
                     } else {
                         $excluded_ttids[] = $tt_ids;
                         $any_non_inclusions = true;
                     }
                 } else {
                     $any_non_inclusions = true;
                     if ('exclude' == $mod_type) {
                         $excluded_ttids[] = array();
                     }
                 }
             }
         }
         if ($excluded_ttids) {
             // don't exclude a term unless it is excluded for all post types
             $exc = $excluded_ttids[0];
             for ($i = 1; $i < count($excluded_ttids); $i++) {
                 $exc = array_intersect($exc, $excluded_ttids[$i]);
             }
             if ($exc) {
                 // but don't exclude a term which is explicitly included for one or more post types
                 if (count($exception_types) > 1) {
                     $all_excluded_ttids = array_merge($all_excluded_ttids, array_diff($exc, $included_ttids));
                 } else {
                     $all_excluded_ttids = array_merge($all_excluded_ttids, $exc);
                 }
             }
         }
         if ($included_ttids) {
             if (empty($wrapped)) {
                 $clauses['where'] = "( {$clauses['where']} )";
                 $wrapped = true;
             }
             // include terms were specified for all post types
             if (count($taxonomies) == 1) {
                 $clauses['where'] = " ( " . $clauses['where'] . " ) AND tt.term_taxonomy_id IN ('" . implode("','", array_unique($included_ttids)) . "')";
             } else {
                 $clauses['where'] .= " AND ( tt.taxonomy != '{$taxonomy}' OR tt.term_taxonomy_id IN ('" . implode("','", array_unique($included_ttids)) . "') )";
             }
         }
     }
     if ($all_excluded_ttids) {
         if (empty($wrapped)) {
             $clauses['where'] = "( {$clauses['where']} )";
             $wrapped = true;
         }
         $clauses['where'] .= " AND tt.term_taxonomy_id NOT IN ('" . implode("','", $all_excluded_ttids) . "')";
     }
     return $clauses;
 }
 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 #13
0
 public static function append_attachment_clause($where, $clauses, $args)
 {
     global $wpdb, $query_interceptor;
     if (!$where) {
         return $where;
     }
     if (!$args) {
         $args = array();
     }
     if (empty($args['src_table'])) {
         $src_table = !empty($args['source_alias']) ? $args['source_alias'] : $wpdb->posts;
         $args['src_table'] = $src_table;
     } else {
         $src_table = $args['src_table'];
     }
     $_args = (array) $args;
     if ($do_parent_subquery = !isset($args['query_contexts']) || !in_array('comments', (array) $args['query_contexts'])) {
         // comment queries don't append parent subquery, but do enforce edit_others_attached_files setting if PPCE is active
         // generate a subquery based on user's permissions to the post attachments are tied to
         $_post_types = array_diff(get_post_types(array('public' => true)), array('attachment'));
         if (!empty($args['limit_ids']) && 1 == count($args['limit_ids'])) {
             if ($_post = get_post(reset($args['limit_ids']))) {
                 if ($_parent_type = array_intersect($_post_types, (array) get_post_field('post_type', $_post->post_parent))) {
                     $_post_types = $_parent_type;
                 }
             }
         }
         $_args['post_types'] = $_post_types;
         // set for parent subquery only
         $_args['source_alias'] = 'p';
         if (!empty($args['has_cap_check'])) {
             unset($_args['limit_statuses']);
         }
         if (empty($_args['limit_statuses'])) {
             $_args['skip_stati_usage_clause'] = true;
         }
         if ('delete' == $_args['required_operation']) {
             if (defined('PP_EDIT_EXCEPTIONS_ALLOW_DELETION') || defined('PP_EDIT_EXCEPTIONS_ALLOW_ATTACHMENT_DELETION')) {
                 $_args['required_operation'] = 'edit';
             }
         }
         $pp_where = $query_interceptor->flt_posts_where('', $_args);
         $type_csv = implode("','", $_post_types);
         $args['subqry'] = "SELECT ID FROM {$wpdb->posts} AS p WHERE 1=1 AND ( p.post_type IN ('{$type_csv}') ) {$pp_where}";
         // pass this into filter even if not applying here
         $args['subqry_args'] = $_args;
         $args['subqry_typecsv'] = $type_csv;
     }
     //if ( ! isset( $args['required_operation'] ) )
     //	$args['required_operation'] = ( pp_is_front() && ! is_preview() ) ? 'read' : 'edit'; // TODO: just ensure this is passed through?
     if ('read' == $args['required_operation']) {
         global $current_user;
         $attached_vis_clause = $do_parent_subquery ? "{$src_table}.post_parent IN ({$args['subqry']})" : "1=1";
         $attached_vis_clause = apply_filters('pp_attached_visibility_clause', $attached_vis_clause, $clauses, $_args);
         $unattached_vis_clause = apply_filters('pp_unattached_visibility_clause', "{$src_table}.post_parent = '0'", $clauses, $_args);
         $own_clause = apply_filters('pp_read_own_attachments', false, $args) ? "{$src_table}.post_author = '{$current_user->ID}' OR " : '';
         if (apply_filters('pp_attachments_allow_unfiltered_parent', class_exists('SlideDeckPlugin', false))) {
             $pp_type_csv = implode("','", array_merge(pp_get_enabled_post_types(), array('revision', 'attachment')));
             $non_pp_parent_clause = " OR ( {$src_table}.post_parent IN ( SELECT ID FROM {$wpdb->posts} WHERE post_type NOT IN ('{$pp_type_csv}') ) )";
         } else {
             $non_pp_parent_clause = '';
         }
         $where = str_replace("{$src_table}.post_type = 'attachment'", "( {$src_table}.post_type = 'attachment' AND ( {$own_clause} ( {$attached_vis_clause} ) OR ( {$unattached_vis_clause} ) {$non_pp_parent_clause} ) )", $where);
     }
     return apply_filters('pp_append_attachment_clause', $where, $clauses, $args);
 }
Example #14
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
    }
 function get_typecast_caps($role_name)
 {
     $arr_name = explode(':', $role_name);
     if (empty($arr_name[2])) {
         return array();
     }
     // this role typecast is not db-defined, so generate it
     $base_role_name = $arr_name[0];
     $src_name = $arr_name[1];
     $object_type = $arr_name[2];
     // typecast role assignment stored, but undefined source name or object_type
     if (!($type_obj = pp_get_type_object($src_name, $object_type))) {
         return array();
     }
     // disregard stored Supplemental Roles for Media when Media is no longer enabled for PP filtering (otherwise Post editing caps are granted)
     if ('attachment' == $object_type) {
         static $media_filtering_enabled;
         if (!isset($media_filtering_enabled)) {
             $media_filtering_enabled = pp_get_enabled_post_types(array('name' => 'attachment'));
         }
         if (!$media_filtering_enabled) {
             return array();
         }
     }
     if (empty($this->pattern_role_type_caps)) {
         $this->define_pattern_caps();
     }
     $pattern_role_caps = 'term' == $src_name ? $this->pattern_role_taxonomy_caps : $this->pattern_role_type_caps;
     if (empty($pattern_role_caps[$base_role_name])) {
         // if the role definition is not currently configured for Pattern Role usage, disregard the assignment
         return array();
     }
     if (!defined('PPS_VERSION') && strpos($role_name, 'post_status:private') && isset($pattern_role_caps[$base_role_name]['read'])) {
         $pattern_role_caps[$base_role_name]['read_private_posts'] = true;
     }
     if (!empty($arr_name[3])) {
         if (empty($arr_name[4])) {
             // disregard stored roles with invalid status
             return array();
         } elseif ('post_status' == $arr_name[3]) {
             // ignore supplemental roles for statuses which are no longer active for this post type
             if (!pp_get_post_stati(array('name' => $arr_name[4], 'post_type' => $object_type))) {
                 return array();
             }
         }
     }
     // add all type-specific caps whose base property cap is included in this pattern role
     // i.e. If 'edit_posts' is in the pattern role, grant $type_obj->cap->edit_posts
     //
     if ($caps = array_intersect_key((array) get_object_vars($type_obj->cap), $pattern_role_caps[$base_role_name])) {
         // At least one type-defined cap is being cast from this pattern role for specified object_type
         $status_caps = apply_filters('pp_get_typecast_caps', $caps, $arr_name, $type_obj);
         if (!empty($arr_name[3]) && false === strpos($role_name, 'post_status:private') && $caps == $status_caps) {
             // if stored status value is invalid, don't credit user for "default statuses" type caps (but allow for subscriber-private if PPS inactive
             return array();
         } else {
             return apply_filters('pp_apply_arbitrary_caps', $status_caps, $arr_name, $type_obj);
         }
     }
     return $caps;
 }
 function post_type_from_caps($caps)
 {
     foreach (pp_get_enabled_post_types(array(), 'object') as $post_type => $type_obj) {
         if (array_intersect((array) $type_obj->cap, $caps)) {
             return $post_type;
         }
     }
     return false;
 }
Example #17
0
 function get_posts_where($args)
 {
     $defaults = array('post_types' => array(), 'source_alias' => false, 'src_table' => '', 'apply_term_restrictions' => true, 'include_trash' => 0, 'required_operation' => '', 'limit_statuses' => false, 'skip_teaser' => false, 'query_contexts' => array(), 'force_types' => false);
     $args = array_merge($defaults, (array) $args);
     extract($args, EXTR_SKIP);
     //d_echo ("<br /><strong>get_posts_where:</strong> <br />");
     global $wpdb;
     if (!$src_table) {
         $src_table = $source_alias ? $source_alias : $wpdb->posts;
         $args['src_table'] = $src_table;
     }
     if (!$force_types) {
         $post_types = array_intersect((array) $post_types, pp_get_enabled_post_types());
     }
     $tease_otypes = array_intersect($post_types, $this->_get_teaser_post_types($post_types, $args));
     if (!$required_operation) {
         $required_operation = pp_is_front() && !is_preview() ? 'read' : 'edit';
         $args['required_operation'] = $required_operation;
     }
     if ($query_contexts) {
         $query_contexts = (array) $query_contexts;
     }
     $meta_cap = "{$required_operation}_post";
     if ('read' == $required_operation) {
         $use_statuses = array_merge(pp_get_post_stati(array('public' => true, 'post_type' => $post_types), 'object'), pp_get_post_stati(array('private' => true, 'post_type' => $post_types), 'object'));
         foreach ($use_statuses as $key => $obj) {
             if (!empty($obj->exclude_from_search)) {
                 // example usage is bbPress hidden status
                 unset($use_statuses[$key]);
             }
         }
     } else {
         $use_statuses = pp_get_post_stati(array('internal' => false, 'post_type' => $post_types), 'object');
     }
     if (in_array('attachment', $post_types)) {
         $use_statuses['inherit'] = (object) array();
     }
     if (is_array($limit_statuses)) {
         $use_statuses = array_intersect_key($use_statuses, $limit_statuses);
     }
     if (empty($skip_teaser) && !array_diff($post_types, $tease_otypes)) {
         // All object types potentially returned by this query will have a teaser filter applied to results, so we don't need to use further query filtering
         $status_clause = "AND {$src_table}.post_status IN ('" . implode("','", array_keys($use_statuses)) . "')";
         return $status_clause;
     }
     if (!is_bool($include_trash)) {
         if (!empty($_REQUEST['post_status']) && 'trash' == $_REQUEST['post_status']) {
             $include_trash = true;
         }
     }
     $where_arr = array();
     global $pp_current_user;
     global $pp_meta_caps;
     $flag_meta_caps = !empty($pp_meta_caps);
     foreach ($post_types as $post_type) {
         if (in_array($post_type, $tease_otypes) && empty($skip_teaser)) {
             $where_arr[$post_type] = "{$src_table}.post_type = '{$post_type}' AND 1=1";
         } else {
             $have_site_caps = array();
             $type_obj = get_post_type_object($post_type);
             foreach (array_keys($use_statuses) as $status) {
                 if ('private' == $status) {
                     $cap_property = "{$required_operation}_private_posts";
                     if (empty($type_obj->cap->{$cap_property})) {
                         continue;
                     }
                 }
                 if ($flag_meta_caps) {
                     $pp_meta_caps->do_status_cap_map = true;
                 }
                 $reqd_caps = pp_map_meta_cap($meta_cap, $pp_current_user->ID, 0, compact('post_type', 'status', 'query_contexts'));
                 if ($flag_meta_caps) {
                     $pp_meta_caps->do_status_cap_map = false;
                 }
                 if ($reqd_caps) {
                     // note: this function is called only for listing query filters (not for user_has_cap filter)
                     if ($missing_caps = apply_filters('pp_query_missing_caps', array_diff($reqd_caps, array_keys($pp_current_user->allcaps)), $reqd_caps, $post_type, $meta_cap)) {
                         $owner_reqd_caps = $this->get_base_caps($reqd_caps, $post_type);
                         // remove "others" and "private" cap requirements for post author
                         if ($owner_reqd_caps != $reqd_caps && $pp_current_user->ID) {
                             // && ! $omit_owner_clause
                             if (!array_diff($owner_reqd_caps, array_keys($pp_current_user->allcaps))) {
                                 $have_site_caps['owner'][] = $status;
                             }
                         }
                     } else {
                         $have_site_caps['user'][] = $status;
                     }
                 }
             }
             $have_site_caps = apply_filters('pp_have_site_caps', $have_site_caps, $post_type, $args);
             if ($include_trash) {
                 if ($type_obj = get_post_type_object($post_type)) {
                     if ('edit_post' == $meta_cap && !empty($pp_current_user->allcaps[$type_obj->cap->edit_posts]) || 'delete_post' == $meta_cap && !empty($pp_current_user->allcaps[$type_obj->cap->delete_posts])) {
                         if (!isset($type_obj->cap->delete_others_posts) || !empty($pp_current_user->allcaps[$type_obj->cap->delete_others_posts])) {
                             $have_site_caps['user'][] = 'trash';
                         } else {
                             $have_site_caps['owner'][] = 'trash';
                         }
                     }
                 }
             }
             $where_arr[$post_type] = array();
             if (!empty($have_site_caps['user'])) {
                 $where_arr[$post_type]['user'] = "******" . implode("','", array_unique($have_site_caps['user'])) . "')";
             }
             //dump($have_site_caps);
             if (!empty($have_site_caps['owner'])) {
                 $parent_clause = '';
                 // PPCE may be set to "ID IN (...) OR " to enable post revisors to edit their own pending revisions
                 $args['post_type'] = $post_type;
                 $_vars = apply_filters('pp_generate_where_clause_force_vars', null, 'post', $args);
                 if (is_array($_vars)) {
                     extract($_vars);
                     // possible @todo: intersect keys as with pp_has_cap_force_vars
                 }
                 if (!empty($args['skip_stati_usage_clause']) && !$limit_statuses && !array_diff_key($use_statuses, array_flip($have_site_caps['owner']))) {
                     $where_arr[$post_type]['owner'] = "{$parent_clause} ( {$src_table}.post_author = {$pp_current_user->ID} )";
                 } else {
                     $where_arr[$post_type]['owner'] = "{$parent_clause} ( {$src_table}.post_author = {$pp_current_user->ID} ) AND {$src_table}.post_status IN ('" . implode("','", array_unique($have_site_caps['owner'])) . "')";
                 }
             }
             if (is_array($where_arr[$post_type])) {
                 if ($where_arr[$post_type]) {
                     $where_arr[$post_type] = pp_implode('OR', $where_arr[$post_type]);
                     $where_arr[$post_type] = "1=1 AND ( " . $where_arr[$post_type] . " )";
                 } else {
                     $where_arr[$post_type] = '1=2';
                 }
             }
             if ($modified = apply_filters('pp_adjust_posts_where_clause', false, $where_arr[$post_type], $post_type, $args)) {
                 $where_arr[$post_type] = $modified;
             }
             if ('attachment' == $post_type) {
                 if ('read' == $required_operation || apply_filters('pp_force_attachment_parent_clause', false, $args)) {
                     //if ( ( 'read' == $required_operation ) || ( defined('DOING_AJAX') && DOING_AJAX && ( false != strpos( $_SERVER['REQUEST_URI'], 'async-upload.php' ) ) ) || apply_filters( 'pp_force_attachment_parent_clause', false, $args ) ) {
                     $where_arr[$post_type] = "( " . $this->append_attachment_clause("{$src_table}.post_type = 'attachment'", array(), $args) . " )";
                 }
             }
             if ('delete' == $required_operation) {
                 $const = "PP_EDIT_EXCEPTIONS_ALLOW_" . strtoupper($post_type) . "_DELETION";
                 if (defined('PP_EDIT_EXCEPTIONS_ALLOW_DELETION') || defined($const)) {
                     $required_operation = 'edit';
                 }
             }
             $where_arr[$post_type] = PP_Exceptions::add_exception_clauses($where_arr[$post_type], $required_operation, $post_type, $args);
         }
     }
     // end foreach post_type
     if (!($pp_where = pp_implode('OR', $where_arr))) {
         $pp_where = '1=1';
     }
     // term restrictions which apply to any post type
     if ($apply_term_restrictions) {
         if ($term_exc_where = PP_Exceptions::add_term_restrictions_clause($required_operation, '', $src_table, array('merge_universals' => true, 'merge_additions' => true, 'exempt_post_types' => $tease_otypes))) {
             $pp_where = "( {$pp_where} ) {$term_exc_where}";
         }
     }
     if ($pp_where) {
         $pp_where = " AND ( {$pp_where} )";
     }
     return $pp_where;
 }
Example #18
0
 public static function flt_get_pages($results, $args = array())
 {
     $results = (array) $results;
     global $wpdb;
     // === BEGIN PP ADDITION: global var; various special case exemption checks ===
     //
     global $pp, $current_user;
     // buffer titles in case they were filtered previously
     $titles = pp_get_property_array($results, 'ID', 'post_title');
     // depth is not really a get_pages arg, but remap exclude arg to exclude_tree if wp_list_terms called with depth=1
     if (!empty($args['exclude']) && empty($args['exclude_tree']) && !empty($args['depth']) && 1 == $args['depth']) {
         if (0 !== strpos($args['exclude'], ',')) {
             // work around wp_list_pages() bug of attaching leading comma if a plugin uses wp_list_pages_excludes filter
             $args['exclude_tree'] = $args['exclude'];
         }
     }
     //
     // === END PP ADDITION ===
     // =================================
     $defaults = array('child_of' => 0, 'sort_order' => 'ASC', 'sort_column' => 'post_title', 'hierarchical' => 1, 'exclude' => array(), 'include' => array(), 'meta_key' => '', 'meta_value' => '', 'authors' => '', 'parent' => -1, 'exclude_tree' => '', 'number' => '', 'offset' => 0, 'post_type' => 'page', 'post_status' => 'publish', 'depth' => 0, 'suppress_filters' => 0, 'required_operation' => '', 'alternate_operation' => '');
     // PP arguments added above
     // === BEGIN PP ADDITION: support front-end optimization
     $post_type = isset($args['post_type']) ? $args['post_type'] : $defaults['post_type'];
     $enabled_post_types = pp_get_enabled_post_types();
     if (defined('PP_UNFILTERED_FRONT')) {
         if (defined('PP_UNFILTERED_FRONT_TYPES')) {
             $unfiltered_types = str_replace(' ', '', PP_UNFILTERED_FRONT_TYPES);
             $unfiltered_types = explode(',', constant($unfiltered_types));
             $enabled_post_types = array_diff($enabled_post_types, $unfiltered_types);
         } else {
             return $results;
         }
     }
     if (!in_array($post_type, $enabled_post_types)) {
         return $results;
     }
     if (pp_is_front()) {
         if ('page' == $post_type && defined('PP_GET_PAGES_LEAN')) {
             // custom types are likely to have custom fields
             $defaults['fields'] = "{$wpdb->posts}.ID, {$wpdb->posts}.post_title, {$wpdb->posts}.post_parent, {$wpdb->posts}.post_date, {$wpdb->posts}.post_date_gmt, {$wpdb->posts}.post_status, {$wpdb->posts}.post_name, {$wpdb->posts}.post_modified, {$wpdb->posts}.post_modified_gmt, {$wpdb->posts}.guid, {$wpdb->posts}.menu_order, {$wpdb->posts}.comment_count";
         } else {
             $defaults['fields'] = "{$wpdb->posts}.*";
         }
     } else {
         // required for xmlrpc getpagelist method
         $defaults['fields'] = "{$wpdb->posts}.*";
     }
     // === END PP MODIFICATION ===
     $r = wp_parse_args($args, $defaults);
     $args['number'] = (int) $r['number'];
     $args['offset'] = absint($r['offset']);
     $args['child_of'] = (int) $r['child_of'];
     extract(apply_filters('pp_get_pages_args', $r), EXTR_SKIP);
     // PPE filter modifies append_page, exclude_tree
     // workaround for CMS Tree Page View (passes post_parent instead of parent)
     if (-1 == $parent && isset($args['post_parent'])) {
         $args['parent'] = $args['post_parent'];
         $parent = $args['post_parent'];
     }
     // Make sure the post type is hierarchical
     $hierarchical_post_types = get_post_types(array('public' => true, 'hierarchical' => true));
     if (!in_array($post_type, $hierarchical_post_types)) {
         return $results;
     }
     // Make sure we have a valid post status
     if (is_admin() && 'any' === $post_status) {
         $post_status = '';
     }
     if ($post_status) {
         if (!is_array($post_status) && strpos($post_status, ',')) {
             $post_status = explode(',', $post_status);
         }
         if (array_diff((array) $post_status, get_post_stati())) {
             return $results;
         }
     }
     $intercepted_pages = apply_filters('pp_get_pages_intercept', false, $results, $args);
     if (is_array($intercepted_pages)) {
         return $intercepted_pages;
     }
     //$pp->last_get_pages_args = $r; // don't copy entire args array unless it proves necessary
     $pp->last_get_pages_depth = $depth;
     $pp->last_get_pages_suppress_filters = $suppress_filters;
     if ($suppress_filters) {
         return $results;
     }
     $orderby_array = array();
     $allowed_keys = array('author', 'post_author', 'date', 'post_date', 'title', 'post_title', 'name', 'post_name', 'modified', 'post_modified', 'modified_gmt', 'post_modified_gmt', 'menu_order', 'parent', 'post_parent', 'ID', 'rand', 'comment_count');
     foreach (explode(',', $sort_column) as $orderby) {
         $orderby = trim($orderby);
         if (!in_array($orderby, $allowed_keys)) {
             continue;
         }
         switch ($orderby) {
             case 'menu_order':
                 break;
             case 'ID':
                 $orderby = "{$wpdb->posts}.ID";
                 break;
             case 'rand':
                 $orderby = 'RAND()';
                 break;
             case 'comment_count':
                 $orderby = "{$wpdb->posts}.comment_count";
                 break;
             default:
                 if (0 === strpos($orderby, 'post_')) {
                     $orderby = "{$wpdb->posts}." . $orderby;
                 } else {
                     $orderby = "{$wpdb->posts}.post_" . $orderby;
                 }
         }
         $orderby_array[] = $orderby;
     }
     $sort_column = !empty($orderby_array) ? implode(',', $orderby_array) : "{$wpdb->posts}.post_title";
     // $args can be whatever, only use the args defined in defaults to compute the key
     $key = md5(serialize(compact(array_keys($defaults))));
     $last_changed = wp_cache_get('last_changed', 'posts');
     if (!$last_changed) {
         $last_changed = microtime();
         wp_cache_set('last_changed', $last_changed, 'posts');
     }
     $cache_key = "pp_get_pages:{$key}:{$last_changed}";
     if ($cache = wp_cache_get($cache_key, 'posts')) {
         // Convert to WP_Post instances
         $pages = array_map('get_post', $cache);
         $pages = apply_filters('pp_get_pages', $pages, $r);
         return $pages;
     }
     $inclusions = '';
     if (!empty($include)) {
         $child_of = 0;
         //ignore child_of, parent, exclude, meta_key, and meta_value params if using include
         $parent = -1;
         $exclude = '';
         $meta_key = '';
         $meta_value = '';
         $hierarchical = false;
         $incpages = wp_parse_id_list($include);
         if (!empty($incpages)) {
             foreach ($incpages as $incpage) {
                 if (empty($inclusions)) {
                     $inclusions = ' AND ( ID = ' . intval($incpage) . ' ';
                 } else {
                     $inclusions .= ' OR ID = ' . intval($incpage) . ' ';
                 }
             }
         }
     }
     if (!empty($inclusions)) {
         $inclusions .= ')';
     }
     $exclusions = '';
     if (!empty($exclude)) {
         $expages = wp_parse_id_list($exclude);
         if (!empty($expages)) {
             foreach ($expages as $expage) {
                 if (empty($exclusions)) {
                     $exclusions = ' AND ( ID <> ' . intval($expage) . ' ';
                 } else {
                     $exclusions .= ' AND ID <> ' . intval($expage) . ' ';
                 }
             }
         }
     }
     if (!empty($exclusions)) {
         $exclusions .= ')';
     }
     $author_query = '';
     if (!empty($authors)) {
         $post_authors = wp_parse_id_list($authors);
         if (!empty($post_authors)) {
             foreach ($post_authors as $post_author) {
                 //Do we have an author id or an author login?
                 if (0 == intval($post_author)) {
                     $post_author = get_user_by('login', $post_author);
                     if (empty($post_author)) {
                         continue;
                     }
                     if (empty($post_author->ID)) {
                         continue;
                     }
                     $post_author = $post_author->ID;
                 }
                 if ('' == $author_query) {
                     $author_query = ' post_author = ' . intval($post_author) . ' ';
                 } else {
                     $author_query .= ' OR post_author = ' . intval($post_author) . ' ';
                 }
             }
             if ('' != $author_query) {
                 $author_query = " AND ({$author_query})";
             }
         }
     }
     $join = '';
     $where = "{$exclusions} {$inclusions} ";
     if (!empty($meta_key) || !empty($meta_value)) {
         $join = " INNER JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id";
         // PP MODIFICATION: was LEFT JOIN in WP 3.0 core
         // meta_key and meta_value might be slashed
         $meta_key = stripslashes($meta_key);
         $meta_value = stripslashes($meta_value);
         if (!empty($meta_key)) {
             $where .= $wpdb->prepare(" AND {$wpdb->postmeta}.meta_key = %s", $meta_key);
         }
         if (!empty($meta_value)) {
             $where .= $wpdb->prepare(" AND {$wpdb->postmeta}.meta_value = %s", $meta_value);
         }
     }
     if ($parent >= 0) {
         $where .= $wpdb->prepare(' AND ' . apply_filters('pp_get_pages_parent', 'post_parent = %d ', $args), $parent);
     }
     // === BEGIN PP MODIFICATION:
     // allow pages of multiple statuses to be displayed (requires default status=publish to be ignored)
     //
     $where_post_type = $wpdb->prepare("post_type = %s", $post_type);
     $where_status = '';
     global $current_user;
     $is_front = pp_is_front();
     if ($is_front && !empty($current_user->ID)) {
         $frontend_list_private = !defined('PP_SUPPRESS_PRIVATE_PAGES');
     } else {
         $frontend_list_private = false;
     }
     $force_publish_status = !$frontend_list_private && 'publish' == $post_status;
     if ($is_front) {
         // since we will be applying status clauses based on content-specific roles, only a sanity check safeguard is needed when post_status is unspecified or defaulted to "publish"
         $safeguard_statuses = array();
         foreach (pp_get_post_stati(array('internal' => false, 'post_type' => $post_type), 'object') as $status_name => $status_obj) {
             if (!$is_front || $status_obj->private || $status_obj->public) {
                 $safeguard_statuses[] = $status_name;
             }
         }
     }
     // WP core does not include private pages in query.  Include private statuses in anticipation of user-specific filtering
     if (is_array($post_status)) {
         $where_status = "AND post_status IN ('" . implode("','", $post_status) . "')";
     } elseif ($post_status && ('publish' != $post_status || $is_front && !$frontend_list_private)) {
         $where_status = $wpdb->prepare("AND post_status = %s", $post_status);
     } elseif ($is_front) {
         $where_status = "AND post_status IN ('" . implode("','", $safeguard_statuses) . "')";
     } else {
         $where_status = "AND post_status NOT IN ('" . implode("','", get_post_stati(array('internal' => true))) . "')";
     }
     $where_id = '';
     global $pagenow;
     if (is_admin() && in_array($pagenow, array('post.php', 'post-new.php'))) {
         global $post;
         if ($post) {
             $where_id = "AND ID != {$post->ID}";
         }
     }
     $where = "AND {$where_post_type} AND ( 1=1 {$where_status} {$where} {$author_query} {$where_id} )";
     $orderby = "ORDER BY {$sort_column} {$sort_order}";
     $limits = !empty($number) ? ' LIMIT ' . $offset . ',' . $number : '';
     $query = "SELECT {$fields} FROM {$wpdb->posts} {$join} WHERE 1=1 {$where} {$orderby} {$limits}";
     if (pp_is_front() && apply_filters('pp_teaser_enabled', false, 'post', $post_type) && !defined('PP_TEASER_HIDE_PAGE_LISTING')) {
         // We are in the front end and the teaser is enabled for pages
         // TODO: move to PPTX
         $query = str_replace("post_status = 'publish'", " post_status IN ('" . implode("','", $safeguard_statuses) . "')", $query);
         $pages = $wpdb->get_results($query);
         // execute unfiltered query
         // Pass results of unfiltered query through the teaser filter.
         // If listing private pages is disabled, they will be omitted completely, but restricted published pages
         // will still be teased.  This is a slight design compromise to satisfy potentially conflicting user goals without yet another option
         $pages = apply_filters('pp_posts_teaser', $pages, $post_type, array('request' => $query, 'force_teaser' => true));
         $tease_all = true;
     } else {
         $_args = array('skip_teaser' => true, 'retain_status' => $force_publish_status);
         $groupby = $distinct = '';
         global $pagenow;
         if (in_array($pagenow, array('post.php', 'post-new.php'))) {
             $clauses = apply_filters('pp_get_pages_clauses', compact('distinct', 'fields', 'join', 'where', 'groupby', 'orderby', 'limits'), $post_type, $args);
         } else {
             // Pass query through the request filter
             $_args['post_types'] = $post_type;
             if ($required_operation) {
                 $_args['required_operation'] = $required_operation;
             } else {
                 $_args['required_operation'] = pp_is_front() && !is_preview() ? 'read' : 'edit';
             }
             if ('edit' == $_args['required_operation'] && isset($args['post_parent']) || 'associate' == $alternate_operation) {
                 // workaround for CMS Page View
                 $_args['alternate_required_ops'] = array('associate');
             }
             $clauses = apply_filters('pp_posts_clauses', compact('distinct', 'fields', 'join', 'where', 'groupby', 'orderby', 'limits'), $_args);
         }
         // Execute the filtered query
         $pages = $wpdb->get_results("SELECT {$distinct} {$clauses['fields']} FROM {$wpdb->posts} {$clauses['join']} WHERE 1=1 {$clauses['where']} {$clauses['orderby']} {$clauses['limits']}");
     }
     if (empty($pages)) {
         // alternate hook name (WP core already applied get_pages filter)
         return apply_filters('pp_get_pages', array(), $r);
     }
     if ($child_of) {
         $pages = get_page_children($child_of, $pages);
     }
     // restore buffered titles in case they were filtered previously
     pp_restore_property_array($pages, $titles, 'ID', 'post_title');
     //
     // === END PP MODIFICATION ===
     // ====================================
     $num_pages = count($pages);
     for ($i = 0; $i < $num_pages; $i++) {
         $pages[$i] = sanitize_post($pages[$i], 'raw');
     }
     // Press Permit note: WP core get_pages has already updated wp_cache and pagecache with unfiltered results.
     update_post_cache($pages);
     // === BEGIN PP MODIFICATION: Support a disjointed pages tree with some parents hidden ========
     if ($child_of || empty($tease_all)) {
         // if we're including all pages with teaser, no need to continue thru tree remapping
         $ancestors = PP_Ancestry::get_page_ancestors();
         // array of all ancestor IDs for keyed page_id, with direct parent first
         $orderby = $sort_column;
         $remap_args = compact('child_of', 'parent', 'exclude', 'depth', 'orderby');
         // one or more of these args may have been modified after extraction
         PP_Ancestry::remap_tree($pages, $ancestors, $remap_args);
     }
     // === END PP MODIFICATION ===
     // ====================================
     if (!empty($exclude_tree)) {
         $exclude = array();
         $exclude = (int) $exclude_tree;
         $children = get_page_children($exclude, $pages);
         // PP note: okay to use unfiltered WP function here since it's only used for excluding
         $excludes = array();
         foreach ($children as $child) {
             $excludes[] = $child->ID;
         }
         $excludes[] = $exclude;
         $total = count($pages);
         for ($i = 0; $i < $total; $i++) {
             if (isset($pages[$i]) && in_array($pages[$i]->ID, $excludes)) {
                 unset($pages[$i]);
             }
         }
     }
     if (!empty($append_page) && !empty($pages)) {
         $found = false;
         foreach (array_keys($pages) as $key) {
             if ($append_page->ID == $pages[$key]->ID) {
                 $found = true;
                 break;
             }
         }
         if (empty($found)) {
             $pages[] = $append_page;
         }
     }
     // re-index the array, just in case anyone cares
     $pages = array_values($pages);
     $page_structure = array();
     foreach ($pages as $page) {
         $page_structure[] = $page->ID;
     }
     wp_cache_set($cache_key, $page_structure, 'posts');
     // Convert to WP_Post instances
     $pages = array_map('get_post', $pages);
     // alternate hook name (WP core already applied get_pages filter)
     return apply_filters('pp_get_pages', $pages, $r);
 }