function ec_getDaysEvents($query) { if (strpos($query, 'eventscalendar_main')) { static $busy; // IMPORTANT: don't execute recursively on db calls below if (empty($busy)) { $busy = true; global $wpdb; static $post_id_in; // local buffer of readable post IDs which are related to any event if (!isset($post_id_in)) { $qry = "SELECT postID FROM {$wpdb->prefix}eventscalendar_main"; $event_ids = scoper_get_col($qry); $event_id_in = "'" . implode("','", $event_ids) . "'"; // now generate and execute a scoped query for readable/unpublished posts $post_qry = "SELECT ID FROM {$wpdb->posts} WHERE 1=1 AND {$wpdb->posts}.ID IN ({$event_id_in})"; // custom arguments to force inclusion of unpublished posts (only relationship to an unreadable published/private posts can make an event unreadable) $reqd_caps = array(); $reqd_caps['post'] = array('publish' => array('read'), 'private' => array('read_private_posts'), 'draft' => array('read'), 'pending' => array('read'), 'future' => array('read')); $post_qry = apply_filters('objects_request_rs', $post_qry, 'post', 'post', array('skip_teaser' => true, 'force_reqd_caps' => $reqd_caps)); $post_ids = scoper_get_col($post_qry); $post_id_in = "'" . implode("','", $post_ids) . "'"; } $id_clause = "( `postID` IS NULL OR `postID` IN ( {$post_id_in} ) ) AND"; $table_name = $wpdb->prefix . 'eventscalendar_main'; $query = str_replace("SELECT * FROM `{$table_name}` WHERE ", "SELECT * FROM `{$table_name}` WHERE {$id_clause} ", $query); $busy = false; } } return $query; }
function scoper_requested_file_rule_expire() { if (scoper_get_option('file_filtering')) { if ($key = scoper_get_option('file_filtering_regen_key')) { if (!empty($_GET['key']) && $key == $_GET['key']) { // user must store their own non-null key before this will work global $wpdb; if (IS_MU_RS) { $blog_ids = scoper_get_col("SELECT blog_id FROM {$wpdb->blogs} ORDER BY blog_id"); $orig_blog_id = $GLOBALS['blog_id']; foreach ($blog_ids as $id) { switch_to_blog($id); scoper_query("DELETE FROM {$wpdb->postmeta} WHERE meta_key = '_rs_file_key'"); } } else { scoper_query("DELETE FROM {$wpdb->postmeta} WHERE meta_key = '_rs_file_key'"); } scoper_expire_file_rules(); if (IS_MU_RS) { _e("File attachment access keys and rewrite rules will be regenerated for each site at next access.", 'scoper'); } else { _e("File attachment access keys and rewrite rules were regenerated.", 'scoper'); } } else { _e('Invalid argument.', 'scoper'); } } else { _e('Please configure File Filtering options!', 'scoper'); } } else { _e('The function is disabled.', 'scoper'); } exit(0); }
function rs_get_post_revisions($post_id, $status = 'inherit', $args = array()) { global $wpdb; $defaults = array('order' => 'DESC', 'orderby' => 'post_modified_gmt', 'use_memcache' => true, 'fields' => COLS_ALL_RS, 'return_flipped' => false, 'where' => ''); $args = wp_parse_args($args, $defaults); extract($args); if (COL_ID_RS == $fields) { // performance opt for repeated calls by user_has_cap filter if ($use_memcache) { static $last_results; if (!isset($last_results)) { $last_results = array(); } elseif (isset($last_results[$post_id][$status])) { return $last_results[$post_id][$status]; } } $revisions = scoper_get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'revision' AND post_parent = '{$post_id}' AND post_status = '{$status}' {$where}"); if ($return_flipped) { $revisions = array_fill_keys($revisions, true); } if ($use_memcache) { if (!isset($last_results[$post_id])) { $last_results[$post_id] = array(); } $last_results[$post_id][$status] = $revisions; } } else { $order_clause = $order && $orderby ? "ORDER BY {$orderby} {$order}" : ''; $revisions = scoper_get_results("SELECT * FROM {$wpdb->posts} WHERE post_type = 'revision' AND post_parent = '{$post_id}' AND post_status = '{$status}' {$order_clause}"); } return $revisions; }
function log_object_save($src_name, $object_id, $is_new_object, $col_parent, $set_parent) { global $wpdb; $is_new_object = true; $qry = "SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE scope = 'object' AND src_or_tx_name = '{$src_name}' AND obj_or_term_id = '{$object_id}'"; if ($assignment_ids = scoper_get_col($qry)) { $is_new_object = false; } else { $qry = "SELECT requirement_id FROM {$wpdb->role_scope_rs} WHERE topic = 'object' AND src_or_tx_name = '{$src_name}' AND obj_or_term_id = '{$object_id}'"; if ($requirement_ids = scoper_get_col($qry)) { $is_new_object = false; } } if ($col_parent) { if (!$is_new_object) { $last_parents = get_option("scoper_last_parents_{$src_name}"); if (!is_array($last_parents)) { $last_parents = array(); } if (isset($last_parents[$object_id])) { $last_parent = $last_parents[$object_id]; } } if (isset($set_parent) && $set_parent != $last_parent && ($set_parent || $last_parent)) { $last_parents[$object_id] = $set_parent; update_option("scoper_last_parents_{$src_name}", $last_parents); } } return $is_new_object; }
function flt_sticky_posts($post_ids) { if ($post_ids && !is_content_administrator_rs()) { global $wpdb; $post_ids = scoper_get_col(apply_filters('objects_request_rs', "SELECT ID FROM {$wpdb->posts} WHERE ID IN ('" . implode("','", $post_ids) . "')", 'post')); } return $post_ids; }
function get_groups_for_user($user_id, $args = array()) { return array(); if (empty($args['no_cache'])) { // use -1 here to ignore accidental storage of other groups for zero user_id $cache = wpp_cache_get(-1, 'group_membership_for_user'); if (is_array($cache)) { return $cache; } } global $wpdb; if (empty($wpdb->groups_rs)) { return array(); } // include WP metagroup for anonymous user $user_groups = scoper_get_col("SELECT {$wpdb->groups_id_col} FROM {$wpdb->groups_rs} WHERE {$wpdb->groups_rs}.{$wpdb->groups_meta_id_col} = 'wp_anon'"); if ($user_groups && empty($args['no_cache'])) { // users should always be in at least a metagroup. Problem with caching empty result on user creation beginning with WP 2.8 $user_groups = array_fill_keys($user_groups, 1); wpp_cache_set(-1, $user_groups, 'group_membership_for_user'); } return $user_groups; }
function filter_objects_listing($mode, &$role_settings, $src, $object_type) { global $wpdb; $filter_args = array(); // only list role assignments which the logged-in user can administer $filter_args['required_operation'] = OP_EDIT_RS; // Possible TODO: re-implement OP_ADMIN distinction with admin-specific capabilities /* global $scoper; if ( cr_get_reqd_caps( $src->name, OP_ADMIN_RS, $object_type ) ) { $filter_args['required_operation'] = OP_ADMIN_RS; } else { $reqd_caps = array(); foreach (array_keys($src->statuses) as $status_name) { $admin_caps = $scoper->cap_defs->get_matching($src->name, $object_type, OP_ADMIN_RS, $status_name); $delete_caps = $scoper->cap_defs->get_matching($src->name, $object_type, OP_DELETE_RS, $status_name); $reqd_caps[$object_type][$status_name] = array_merge(array_keys($admin_caps), array_keys($delete_caps)); } $filter_args['force_reqd_caps'] = $reqd_caps; } */ $qry = "SELECT {$src->table}.{$src->cols->id} FROM {$src->table} WHERE 1=1 AND {$src->cols->type} = '{$object_type}'"; //$filter_args['require_full_object_role'] = true; $qry_flt = apply_filters('objects_request_rs', $qry, $src->name, $object_type, $filter_args); if ($cu_admin_results = scoper_get_col($qry_flt)) { $cu_admin_results = array_fill_keys($cu_admin_results, true); } if (ROLE_ASSIGNMENT_RS == $mode) { foreach (array_keys($role_settings) as $role_basis) { foreach (array_keys($role_settings[$role_basis]) as $obj_id) { if (!isset($cu_admin_results[$obj_id])) { unset($role_settings[$role_basis][$obj_id]); } } } } else { $setting_types = array('restrictions', 'unrestrictions'); foreach ($setting_types as $setting_type) { if (isset($role_settings[$setting_type])) { foreach (array_keys($role_settings[$setting_type]) as $role_handle) { foreach (array_keys($role_settings[$setting_type][$role_handle]) as $obj_id) { if (!isset($cu_admin_results[$obj_id])) { unset($role_settings[$setting_type][$role_handle][$obj_id]); } } } } } } return $cu_admin_results; }
function groups_who_can($reqd_caps, $cols = COLS_ALL_RS, $object_src_name = '', $object_id = 0, $args = array()) { global $wpdb; $defaults = array('orderby' => '', 'disable_memcache' => false, 'force_refresh' => false); $args = array_merge($defaults, (array) $args); extract($args); $cache_flag = "rs_groups_who_can"; $cache_id = md5(serialize($reqd_caps) . $cols . 'src' . $object_src_name . 'id' . $object_id . serialize($args)); if (!$force_refresh) { $groups = wpp_cache_get($cache_id, $cache_flag); if (is_array($groups)) { return $groups; } } if (!is_array($reqd_caps)) { $reqd_caps = $reqd_caps ? array($reqd_caps) : array(); } if (!$orderby && (COLS_ALL_RS == $cols || COLS_ID_DISPLAYNAME_RS == $cols)) { $orderby = " ORDER BY display_name"; } if (!is_array($args)) { $args = array(); } if (isset($args['ignore_group_roles'])) { unset($args['ignore_group_roles']); } $args['ignore_user_roles'] = 1; $args['querying_groups'] = 1; $where = $this->flt_users_where('', $reqd_caps, $object_src_name, $object_id, $args); if (COL_ID_RS == $cols) { $qry = "SELECT DISTINCT group_id as ID FROM {$wpdb->user2role2object_rs} AS gro WHERE 1=1 {$where} AND gro.group_id > 0 {$orderby}"; $groups = scoper_get_col($qry); } else { $grp = $wpdb->groups_rs; $qry = "SELECT DISTINCT {$grp}.{$wpdb->groups_id_col} AS ID, {$grp}.{$wpdb->groups_name_col} AS display_name, {$grp}.{$wpdb->groups_descript_col} as descript FROM {$grp}" . " INNER JOIN {$wpdb->user2group_rs} as u2g ON u2g.{$wpdb->user2group_gid_col} = {$grp}.{$wpdb->groups_id_col}" . " INNER JOIN {$wpdb->user2role2object_rs} AS gro ON {$grp}.{$wpdb->groups_id_col} = gro.group_id WHERE 1=1 {$where} {$orderby}"; $groups = scoper_get_results($qry); } wpp_cache_set($cache_id, $groups, $cache_flag); return $groups; }
function scoper_limit_subscribe2_autosub($query) { global $wpdb; if ("SELECT DISTINCT user_id FROM {$wpdb->usermeta} WHERE {$wpdb->usermeta}.meta_key='s2_autosub' AND {$wpdb->usermeta}.meta_value='yes'" == $query) { global $scoper, $subscribe2_category_rs; //rs_errlog("subscribe2 cat creation: $subscribe2_category_rs"); $post_roles = $scoper->role_defs->qualify_roles('read', 'rs', 'post'); // WP roles containing the 'activate plugins' capability are always honored regardless of object or term restritions $admin_roles_wp = array(); global $wp_roles; if (isset($wp_roles->roles)) { $admin_cap_name = defined('SCOPER_CONTENT_ADMIN_CAP') ? constant('SCOPER_CONTENT_ADMIN_CAP') : 'activate_plugins'; foreach (array_keys($wp_roles->roles) as $wp_role_name) { if (!empty($wp_roles->roles[$wp_role_name]['capabilities'])) { if (array_intersect_key($wp_roles->roles[$wp_role_name]['capabilities'], array($admin_cap_name => 1))) { $admin_roles_wp = array_merge($admin_roles_wp, array($wp_role_name => 1)); } } } } if ($admin_roles_wp) { $admin_roles_wp = scoper_role_names_to_handles(array_keys($admin_roles_wp), 'wp', true); } //arg: return as array keys $args = array('id' => $subscribe2_category_rs); $restrictions = $scoper->get_restrictions(TERM_SCOPE_RS, 'category', $args); $restricted_roles = array(); if (!empty($restrictions['unrestrictions'])) { if ($restrictions['unrestrictions'] = array_intersect_key($restrictions['unrestrictions'], $post_roles)) { foreach ($restrictions['unrestrictions'] as $role_handle => $entries) { if (!isset($entries[$subscribe2_category_rs]) || 'children' == $entries[$subscribe2_category_rs]) { $restricted_roles[$role_handle] = true; } } } } if (!empty($restrictions['restrictions'])) { if ($restrictions['restrictions'] = array_intersect_key($restrictions['restrictions'], $post_roles)) { foreach ($restrictions['restrictions'] as $role_handle => $entries) { if (isset($entries[$subscribe2_category_rs]) && 'children' != $entries[$subscribe2_category_rs]) { $restricted_roles[$role_handle] = true; } } } } $unrestricted_roles = array_diff_key($post_roles, $restricted_roles); // for our purposes, a role is only restricted if all its contained qualifying roles are also restricted if ($restricted_roles) { foreach (array_keys($restricted_roles) as $role_handle) { if ($contained_roles = $scoper->role_defs->get_contained_roles($role_handle, false, 'rs')) { if ($contained_roles = array_intersect_key($contained_roles, $unrestricted_roles)) { unset($restricted_roles[$role_handle]); } } } $unrestricted_roles = array_diff_key($post_roles, $restricted_roles); } // account for WP blog roles $unrestricted_roles_wp = array(); $restricted_roles_wp = array(); if ($post_roles_wp = $scoper->role_defs->qualify_roles('read', 'wp', 'post')) { foreach (array_keys($post_roles_wp) as $wp_role) { if ($contains_rs_roles = $scoper->role_defs->get_contained_roles($wp_role, false, 'rs')) { if ($contains_rs_roles = array_intersect_key($contains_rs_roles, $unrestricted_roles)) { $unrestricted_roles_wp = array_merge($unrestricted_roles_wp, array($wp_role => true)); } } } $restricted_roles_wp = array_diff_key($post_roles_wp, $unrestricted_roles_wp); } $unrestricted_roles_wp = array_merge($unrestricted_roles_wp, $admin_roles_wp); $role_in_wp = implode("', '", scoper_role_handles_to_names(array_keys($unrestricted_roles_wp))); /* dump($post_roles); dump($restricted_roles); dump($restricted_roles_wp); dump($unrestricted_roles); dump($unrestricted_roles_wp); */ // account for blog roles, where allowed if ($unrestricted_roles) { $wp_role_clause = !empty($role_in_wp) ? "OR ( role_type = 'wp' AND scope = 'blog' AND role_name IN ('{$role_in_wp}') )" : ''; $role_in = implode("', '", scoper_role_handles_to_names(array_keys($unrestricted_roles))); $qry = "SELECT DISTINCT user_id FROM {$wpdb->user2role2object_rs}" . " WHERE user_id > 0 AND (" . " ( role_type = 'rs' AND scope = 'blog' AND role_name IN ('{$role_in}') ) {$wp_role_clause} )"; $users = scoper_get_col($qry); $qry = "SELECT DISTINCT group_id FROM {$wpdb->user2role2object_rs}" . " WHERE group_id > 0 AND (" . " ( role_type = 'rs' AND scope = 'blog' AND role_name IN ('{$role_in}') ) {$wp_role_clause} )"; if ($groups = scoper_get_col($qry)) { foreach ($groups as $group_id) { if ($group_members = ScoperAdminLib::get_group_members($group_id, $cols, true)) { $users = array_merge($users, $group_members); } } $users = array_unique($users); } } else { $users = array(); } // account for category roles $role_in = implode("', '", scoper_role_handles_to_names(array_keys($post_roles))); $qry = "SELECT DISTINCT user_id FROM {$wpdb->user2role2object_rs}" . " WHERE user_id > 0 AND role_type = 'rs' AND scope = 'term' AND role_name IN ('{$role_in}')" . " AND assign_for IN ('entity', 'both')" . " AND src_or_tx_name = 'category' AND obj_or_term_id = '{$subscribe2_category_rs}'"; $catrole_users = scoper_get_col($qry); $users = array_merge($users, $catrole_users); $qry = "SELECT DISTINCT group_id FROM {$wpdb->user2role2object_rs}" . " WHERE group_id > 0 AND role_type = 'rs' AND scope = 'term' AND role_name IN ('{$role_in}')" . " AND assign_for IN ('entity', 'both')" . " AND src_or_tx_name = 'category' AND obj_or_term_id = '{$subscribe2_category_rs}'"; if ($groups = scoper_get_col($qry)) { foreach ($groups as $group_id) { if ($group_members = ScoperAdminLib::get_group_members($group_id, $cols, true)) { $users = array_merge($users, $group_members); } } $users = array_unique($users); } if ($users) { $query .= " AND user_id IN ('" . implode("', '", $users) . "')"; } else { $query .= ' AND 1=2'; } remove_filter('query', 'scoper_limit_subscribe2_autosub', 99); } return $query; }
function get_applied_object_roles($user = '') { if (is_object($user)) { $cache_flag = 'rs_object-roles'; // v 1.1: changed cache key from "object_roles" to "object-roles" to match new key format for blog, term roles $cache = $user->cache_get($cache_flag); $limit = ''; $u_g_clause = $user->get_user_clause(''); } else { $cache_flag = 'rs_applied_object-roles'; // v 1.1: changed cache key from "object_roles" to "object-roles" to match new key format for blog, term roles $cache_id = 'all'; $cache = wpp_cache_get($cache_id, $cache_flag); $u_g_clause = ''; } if (is_array($cache)) { return $cache; } $role_handles = array(); global $wpdb; // object roles support date limits, but content date limits (would be redundant and a needless performance hit) $duration_clause = scoper_get_duration_clause('', $wpdb->user2role2object_rs); if ($role_names = scoper_get_col("SELECT DISTINCT role_name FROM {$wpdb->user2role2object_rs} WHERE role_type='rs' AND scope='object' {$duration_clause} {$u_g_clause}")) { $role_handles = scoper_role_names_to_handles($role_names, 'rs', true); } //arg: return role keys as array key if (is_object($user)) { $user->cache_force_set($role_handles, $cache_flag); } else { wpp_cache_force_set($cache_id, $role_handles, $cache_flag); } return $role_handles; }
function update_rs_role_defs($sitewide = false, $customize_defaults = false) { $default_prefix = $customize_defaults ? 'default_' : ''; $default_role_caps = apply_filters('define_role_caps_rs', cr_role_caps()); $cap_defs = new CR_Capabilities(); $cap_defs = apply_filters('define_capabilities_rs', $cap_defs); $cap_defs->add_member_objects(cr_cap_defs()); global $scoper, $scoper_role_types; $role_defs = new CR_Roles(); $role_defs->add_member_objects(cr_role_defs()); $role_defs = apply_filters('define_roles_rs', $role_defs); $reviewed_roles = explode(',', $_POST['reviewed_roles']); $disable_caps = array(); $add_caps = array(); foreach ($default_role_caps as $role_handle => $default_caps) { if (!in_array($role_handle, $reviewed_roles)) { continue; } if ($role_defs->member_property($role_handle, 'no_custom_caps') || $role_defs->member_property($role_handle, 'anon_user_blogrole')) { continue; } $posted_set_caps = empty($_POST["{$role_handle}_caps"]) ? array() : $_POST["{$role_handle}_caps"]; // html IDs have any spaces stripped out of cap names. Replace them for processing. $set_caps = array(); foreach ($posted_set_caps as $cap_name) { if (strpos($cap_name, ' ')) { $set_caps[] = str_replace('_', ' ', $cap_name); } else { $set_caps[] = $cap_name; } } // deal with caps which are locked into role, therefore displayed as a disabled checkbox and not included in $_POST foreach (array_keys($default_caps) as $cap_name) { if (!in_array($cap_name, $set_caps) && $cap_defs->member_property($cap_name, 'no_custom_remove')) { $set_caps[] = $cap_name; } } $disable_caps[$role_handle] = array_fill_keys(array_diff(array_keys($default_caps), $set_caps), true); $add_caps[$role_handle] = array_fill_keys(array_diff($set_caps, array_keys($default_caps)), true); } scoper_update_option($default_prefix . 'disabled_role_caps', $disable_caps, $sitewide); scoper_update_option($default_prefix . 'user_role_caps', $add_caps, $sitewide); scoper_refresh_options(); $scoper->load_definition('cap_defs'); global $wp_roles; // synchronize WP roles as requested if (!empty($_POST['sync_wp_roles'])) { foreach ($_POST['sync_wp_roles'] as $sync_request) { $scoper->log_cap_usage($scoper->role_defs, $scoper->cap_defs); $sync_handles = explode(':', $sync_request); $rs_role_handle = $sync_handles[0]; $wp_role_handle = $sync_handles[1]; $wp_role_name = str_replace('wp_', '', $wp_role_handle); // only remove caps which are defined for this RS role's data source and object type $role_attributes = $scoper->role_defs->get_role_attributes($rs_role_handle); $otype_caps = $scoper->cap_defs->get_matching($role_attributes->src_name, $role_attributes->object_type, '', STATUS_ANY_RS); // make the roledef change for all blogs if RS role def is sitewide if (IS_MU_RS && $sitewide) { global $wpdb, $blog_id; $blog_ids = scoper_get_col("SELECT blog_id FROM {$wpdb->blogs}"); $orig_blog_id = $blog_id; } else { $blog_ids = array(''); } foreach ($blog_ids as $id) { if (count($blog_ids) > 1) { switch_to_blog($id); } if (!isset($wp_roles->role_objects[$wp_role_name])) { continue; } if ($wp_missing_caps = array_diff_key($scoper->role_defs->role_caps[$rs_role_handle], $wp_roles->role_objects[$wp_role_name]->capabilities)) { foreach (array_keys($wp_missing_caps) as $cap_name) { $wp_roles->add_cap($wp_role_name, $cap_name); } } $wp_defined_caps = array_intersect_key($wp_roles->role_objects[$wp_role_name]->capabilities, $otype_caps); if ($wp_extra_caps = array_diff_key($wp_defined_caps, $scoper->role_defs->role_caps[$rs_role_handle])) { foreach (array_keys($wp_extra_caps) as $cap_name) { $wp_roles->remove_cap($wp_role_name, $cap_name); } } } if (count($blog_ids) > 1) { switch_to_blog($orig_blog_id); } $wp_roles = new WP_Roles(); } } $scoper->role_defs->locked = false; $scoper->log_wp_roles($scoper->role_defs); $scoper->role_defs->lock(); }
function flt_nav_menu_items($items, $menu_name, $args) { global $wpdb; $item_types = array(); foreach ($items as $key => $item) { if (!isset($item_types[$item->type])) { $item_types["{$item->type}"] = array(); } if (!isset($item_types[$item->type][$item->object])) { $item_types[$item->type][$item->object] = array($key => $item->object_id); } else { $item_types[$item->type][$item->object][$key] = $item->object_id; } } $teaser_enabled = scoper_get_otype_option('do_teaser', 'post'); // remove unreadable terms if (isset($item_types['taxonomy'])) { foreach ($item_types['taxonomy'] as $taxonomy => $item_ids) { if ($teaser_enabled) { if ($taxonomy_obj = get_taxonomy($taxonomy)) { foreach ($taxonomy_obj->object_type as $post_type) { // don't remove a term if it is associated with a post type that's being teased if (scoper_get_otype_option('use_teaser', 'post', $post_type)) { continue 2; } } } } /* $query_base = "SELECT t.term_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE 1=1 AND tt.taxonomy = '$taxonomy'"; $query = apply_filters( 'terms_request_rs', $query_base, $taxonomy ); //, array( 'skip_teaser' => true ) ); $okay_ids = scoper_get_col($query); */ $hide_empty = isset($args['hide_empty']) ? $args['hide_empty'] : 0; $okay_ids = get_terms($taxonomy, "fields=ids&hierarchical=0&hide_empty={$hide_empty}"); if ($remove_ids = array_diff($item_ids, $okay_ids)) { $items = array_diff_key($items, $remove_ids); } } } // remove unreadable posts if (isset($item_types['post_type'])) { foreach ($item_types['post_type'] as $post_type => $item_ids) { $where = apply_filters('objects_where_rs', '', 'post', $post_type, array('skip_teaser' => true)); $okay_ids = scoper_get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type = '{$post_type}' {$where} AND ID IN ('" . implode("','", $item_ids) . "')"); if ($remove_ids = array_diff($item_ids, $okay_ids)) { if ($teaser_enabled && scoper_get_otype_option('use_teaser', 'post', $post_type)) { require_once dirname(__FILE__) . '/teaser_rs.php'; $teaser_prepend = ScoperTeaser::get_teaser_text('prepend', 'name', 'post', $post_type); $teaser_append = ScoperTeaser::get_teaser_text('append', 'name', 'post', $post_type); foreach (array_keys($remove_ids) as $key) { $items[$key]->title = $teaser_prepend . $items[$key]->title . $teaser_append; } } else { $items = array_diff_key($items, $remove_ids); } } } } return $items; }
function item_deletion_aftermath($scope, $src_or_tx_name, $obj_or_term_id) { global $wpdb; // delete role assignments for deleted term if ($ass_ids = scoper_get_col("SELECT assignment_id FROM {$wpdb->user2role2object_rs} WHERE src_or_tx_name = '{$src_or_tx_name}' AND scope = '{$scope}' AND obj_or_term_id = '{$obj_or_term_id}'")) { $id_in = "'" . implode("', '", $ass_ids) . "'"; scoper_query("DELETE FROM {$wpdb->user2role2object_rs} WHERE assignment_id IN ({$id_in})"); // Propagated roles will be converted to direct-assigned roles if the original progenetor goes away. Removal of a "link" in the parent/child propagation chain has no effect. scoper_query("UPDATE {$wpdb->user2role2object_rs} SET inherited_from = '0' WHERE inherited_from IN ({$id_in})"); } if ($req_ids = scoper_get_col("SELECT requirement_id FROM {$wpdb->role_scope_rs} WHERE topic = '{$scope}' AND src_or_tx_name = '{$src_or_tx_name}' AND obj_or_term_id = '{$obj_or_term_id}'")) { $id_in = "'" . implode("', '", $req_ids) . "'"; scoper_query("DELETE FROM {$wpdb->role_scope_rs} WHERE requirement_id IN ({$id_in})"); // Propagated requirements will be converted to direct-assigned roles if the original progenetor goes away. Removal of a "link" in the parent/child propagation chain has no effect. scoper_query("UPDATE {$wpdb->role_scope_rs} SET inherited_from = '0' WHERE inherited_from IN ({$id_in})"); } }
function clear_all_file_rules() { global $wpdb, $blog_id; $blog_ids = scoper_get_col("SELECT blog_id FROM {$wpdb->blogs} ORDER BY blog_id"); $orig_blog_id = $blog_id; foreach ($blog_ids as $id) { switch_to_blog($id); require_once dirname(__FILE__) . '/uploads_rs.php'; $uploads = scoper_get_upload_info(); $htaccess_path = trailingslashit($uploads['basedir']) . '.htaccess'; if (file_exists($htaccess_path)) { ScoperRewrite::insert_with_markers($htaccess_path, 'Role Scoper', ''); } } switch_to_blog($orig_blog_id); }
function objects_where_scope_clauses($src_name, $reqd_caps, $args) { // Optional Args (will be defaulted to meaningful values) // Note: ignore_restrictions affects Scoper::qualify_terms() output $defaults = array('taxonomies' => '', 'use_blog_roles' => true, 'terms_query' => false, 'qualifying_object_roles' => false, 'skip_objscope_check' => false, 'require_full_object_role' => false, 'objrole_revisions_clause' => false, 'ignore_restrictions' => false); // Required Args // NOTE: use_object_roles is a boolean for the single object_type in question, but use_term_roles is array[taxonomy] = true or false $required = array_fill_keys(array('user', 'object_type', 'qualifying_roles', 'otype_use_term_roles', 'otype_use_object_roles'), true); if ($missing = array_diff_key($required, $args)) { rs_notice(sprintf('Role Scoper Runtime Error (%1$s) - Missing argument(s): %2$s', 'objects_where_scope_clauses', implode(", ", array_keys($missing)))); return ' 1=2 '; } $defaults = array_merge($defaults, $required); $args = array_merge($defaults, (array) $args); extract($args); if (!($src = $this->scoper->data_sources->get($src_name))) { rs_notice(sprintf('Role Scoper Config Error (%1$s): Data source (%2$s) is not defined.', 'objects_where_scope_clauses', $src_name)); return ' 1=2 '; } $src_table = !empty($source_alias) ? $source_alias : $src->table; if ('group' == $src_name) { $otype_use_object_roles = true; } elseif (!empty($src->no_object_roles)) { $otype_use_object_roles = false; } // primary qualifying_roles array should contain only RS roles $qualifying_roles = $this->scoper->role_defs->filter($qualifying_roles, array('role_type' => 'rs'), 'names_as_key'); if ($otype_use_object_roles) { // For object assignment, replace any "others" reqd_caps array. // Also exclude any roles which have never been assigned to any object if (!is_array($qualifying_object_roles)) { $qualifying_object_roles = $this->scoper->confirm_object_scope($qualifying_roles, $user); } if ($skip_objscope_check) { $objscope_objects = array(); } else { $objscope_objects = $this->scoper->get_restrictions(OBJECT_SCOPE_RS, $src_name); } // this is buffered so redundant calling is not a concern } //--------------------------------------------------------------------------------- //dump($qualifying_object_roles); //dump($objscope_objects); if ($otype_use_object_roles) { $user_qualifies_for_obj_roles = $user->ID || defined('SCOPER_ANON_METAGROUP'); } $where = array(); if ($terms_query) { $_taxonomies = $taxonomies; } elseif ($otype_use_term_roles && is_array($otype_use_term_roles)) { $_taxonomies = array_keys(array_intersect($otype_use_term_roles, array(1, '1', true))); // taxonomies arg is for limiting; default is to include all associated taxonomies in where clause if ($taxonomies) { $_taxonomies = array_intersect($_taxonomies, $taxonomies); } } else { $_taxonomies = array(); } if ($_taxonomies && 'post' == $src_name) { $enabled_taxonomies = array_keys(array_intersect(scoper_get_option('use_taxonomies'), array(1, '1', true))); $_taxonomies = array_intersect($_taxonomies, $enabled_taxonomies); } $user_blog_roles = array('' => array()); if ($use_blog_roles) { foreach (array_keys($user->blog_roles) as $date_key) { $user_blog_roles[$date_key] = array_intersect_key($user->blog_roles[$date_key], $qualifying_roles); } // Also include user's WP blogrole(s), // but via equivalent RS role(s) to support scoping requirements (strict (i.e. restricted) terms, objects) if ($wp_qualifying_roles = $this->scoper->role_defs->qualify_roles($reqd_caps, 'wp')) { if ($user_blog_roles_wp = array_intersect_key($user->blog_roles[ANY_CONTENT_DATE_RS], $wp_qualifying_roles)) { // Credit user's qualifying WP blogrole via contained RS role(s) // so we can also enforce "term restrictions", which are based on RS roles $user_blog_roles_via_wp = $this->scoper->role_defs->get_contained_roles(array_keys($user_blog_roles_wp), false, 'rs'); $user_blog_roles_via_wp = array_intersect_key($user_blog_roles_via_wp, $qualifying_roles); $user_blog_roles[ANY_CONTENT_DATE_RS] = array_merge($user_blog_roles[ANY_CONTENT_DATE_RS], $user_blog_roles_via_wp); } } } /* // --- optional hack to require read_private cap via blog role AND object role // if the required capabilities include a read_private cap but no edit caps $require_blog_and_obj_role = ( in_array('read_private_posts', $reqd_caps) || in_array('read_private_pages', $reqd_caps) ) && ( ! array_diff( $reqd_caps, array('read_private_posts', 'read_private_pages', 'read') ) ); // --- end hack --- */ //dump($qualifying_roles); //dump($objscope_objects); foreach (array_keys($qualifying_roles) as $role_handle) { //dump($role_handle); if ($otype_use_object_roles && empty($require_blog_and_obj_role)) { if (!empty($objscope_objects['restrictions'][$role_handle])) { $objscope_clause = " AND {$src_table}.{$src->cols->id} NOT IN ('" . implode("', '", array_keys($objscope_objects['restrictions'][$role_handle])) . "')"; } elseif (isset($objscope_objects['unrestrictions'][$role_handle])) { if (!empty($objscope_objects['unrestrictions'][$role_handle])) { $objscope_clause = " AND {$src_table}.{$src->cols->id} IN ('" . implode("', '", array_keys($objscope_objects['unrestrictions'][$role_handle])) . "')"; } else { $objscope_clause = " AND 1=2"; } // role is default-restricted for this object type, but objects are unrestrictions are set } else { $objscope_clause = ''; } } else { $objscope_clause = ''; } //dump($objscope_clause); $all_terms_qualified = array(); $all_taxonomies_qualified = array(); if ($_taxonomies) { $args['return_id_type'] = COL_TAXONOMY_ID_RS; $strict_taxonomies = array(); foreach ($_taxonomies as $taxonomy) { if ($this->scoper->taxonomies->member_property($taxonomy, 'requires_term')) { $strict_taxonomies[$taxonomy] = true; } } foreach ($_taxonomies as $taxonomy) { // we only need a separate clause for each role if considering object roles (and therefore considering that some objects might require some roles to be object-assigned) if (!$otype_use_object_roles) { $role_handle_arg = $qualifying_roles; } else { $role_handle_arg = array($role_handle => 1); } // If a taxonomy does not require objects to have a term, its term role assignments // will be purely supplemental; there is no basis for ignoring blogrole assignments. // // So if none of the taxonomies require each object to have a term // AND the user has a qualifying role via blog assignment, we can skip the taxonomies clause altogether. // Otherwise, will consider current user's termroles if (!$strict_taxonomies) { if (array_intersect_key($role_handle_arg, $user->blog_roles[ANY_CONTENT_DATE_RS])) { // User has a qualifying role by blog assignment, so term_id clause is not required $all_taxonomies_qualified[ANY_CONTENT_DATE_RS] = true; break; } } // qualify_terms returns: // terms for which current user has a qualifying role // - AND - // which are non-restricted (i.e. blend in blog assignments) for a qualifying role which the user has blog-wide // // note: $reqd_caps function arg is used; qualify_terms will ignore reqd_caps element in args array if ($user_terms = $this->scoper->qualify_terms_daterange($reqd_caps, $taxonomy, $role_handle_arg, $args)) { if (!isset($term_count[$taxonomy])) { $term_count[$taxonomy] = $this->scoper->get_terms($taxonomy, UNFILTERED_RS, COL_COUNT_RS); } foreach (array_keys($user_terms) as $date_key) { if (count($user_terms[$date_key])) { // don't bother applying term requirements if user has cap for all terms in this taxonomy if (count($user_terms[$date_key]) >= $term_count[$taxonomy] && $this->scoper->taxonomies->member_property($taxonomy, 'requires_term')) { // User is qualified for all terms in this taxonomy; no need for any term_id clauses $all_terms_qualified[$date_key][$taxonomy] = true; } else { $where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy] = isset($where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy]) ? array_unique(array_merge($where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy], $user_terms[$date_key])) : $user_terms[$date_key]; } } $all_taxonomies_qualified[$date_key] = !empty($all_terms_qualified[$date_key]) && count($all_terms_qualified[$date_key]) == count($strict_taxonomies); } } } // end foreach taxonomy } foreach (array_keys($user_blog_roles) as $date_key) { if (!empty($all_taxonomies_qualified[$date_key]) || !$_taxonomies && !empty($user_blog_roles[$date_key][$role_handle])) { if ($date_key || $objscope_clause || !empty($require_blog_and_obj_role)) { $where[$date_key][$objscope_clause][BLOG_SCOPE_RS] = "1=1"; } else { return "1=1"; // no need to include other clause if user has a qualifying role blog-wide or in all terms, it is not date-limited, and that role does not require object assignment for any objects } } } // if object roles should be applied, populatate array key to force inclusion of OBJECT_SCOPE_RS query clauses below if ($otype_use_object_roles && isset($qualifying_object_roles[$role_handle]) && $user_qualifies_for_obj_roles) { // want to apply objscope requirements for anon user, but not apply any obj roles if ($role_spec = scoper_explode_role_handle($role_handle)) { $where[ANY_CONTENT_DATE_RS][NO_OBJSCOPE_CLAUSE_RS][OBJECT_SCOPE_RS][$role_spec->role_type][$role_spec->role_name] = true; } } // we only need a separate clause for each role if considering object roles (and therefore considering that some objects might require some roles to be object-assigned) if (!$otype_use_object_roles && !empty($where[ANY_CONTENT_DATE_RS])) { break; } } // end foreach role // also include object scope clauses for any roles which qualify only for object-assignment if ($otype_use_object_roles && isset($qualifying_object_roles) && $user_qualifies_for_obj_roles) { // want to apply objscope requirements for anon user, but not apply any obj roles if ($obj_only_roles = array_diff_key($qualifying_object_roles, $qualifying_roles)) { foreach (array_keys($obj_only_roles) as $role_handle) { if ($role_spec = scoper_explode_role_handle($role_handle)) { $where[ANY_CONTENT_DATE_RS][NO_OBJSCOPE_CLAUSE_RS][OBJECT_SCOPE_RS][$role_spec->role_type][$role_spec->role_name] = true; } } } } // DB query perf enhancement: if any terms are included regardless of post ID, don't also include those terms in ID-specific clause foreach (array_keys($where) as $date_key) { foreach (array_keys($where[$date_key]) as $objscope_clause) { if ($objscope_clause && isset($where[$date_key][$objscope_clause][TERM_SCOPE_RS])) { foreach ($where[$date_key][$objscope_clause][TERM_SCOPE_RS] as $taxonomy => $terms) { if (!empty($terms) && !empty($where[$date_key][NO_OBJSCOPE_CLAUSE_RS][TERM_SCOPE_RS][$taxonomy])) { $where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy] = array_diff($where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy], $where[$date_key][NO_OBJSCOPE_CLAUSE_RS][TERM_SCOPE_RS][$taxonomy]); if (empty($where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy])) { unset($where[$date_key][$objscope_clause][TERM_SCOPE_RS][$taxonomy]); // if we removed a taxonomy array, don't leave behind a term scope array with no taxonomies if (empty($where[$date_key][$objscope_clause][TERM_SCOPE_RS])) { unset($where[$date_key][$objscope_clause][TERM_SCOPE_RS]); // if we removed a term scope array, don't leave behind an objscope array with no scopes if (empty($where[$date_key][$objscope_clause])) { unset($where[$date_key][$objscope_clause]); } } } } } } } } // since object roles are not pre-loaded prior to this call, role date limits are handled via subselect, within the date_key = '' iteration $object_roles_duration_clause = scoper_get_duration_clause(); // implode the array of where criteria into a query as concisely as possible foreach ($where as $date_key => $objscope_clauses) { foreach ($objscope_clauses as $objscope_clause => $scope_criteria) { foreach (array_keys($scope_criteria) as $scope) { switch ($scope) { case BLOG_SCOPE_RS: $where[$date_key][$objscope_clause][BLOG_SCOPE_RS] = $where[$date_key][$objscope_clause][BLOG_SCOPE_RS] . " {$objscope_clause}"; break; case TERM_SCOPE_RS: $taxonomy_clauses = array(); foreach ($scope_criteria[TERM_SCOPE_RS] as $taxonomy => $terms) { $is_strict = !empty($strict_taxonomies[$taxonomy]); if ($objscope_clause) { // Avoid " term_id IN (5) OR ( term_id IN (5) AND ID NOT IN (100) ) // Otherwise this redundancy can occur when various qualifying roles require object role assignment for different objects if (!empty($where[$date_key][NO_OBJSCOPE_CLAUSE_RS][TERM_SCOPE_RS][$taxonomy])) { if (!($terms = array_diff($terms, $where[$date_key][NO_OBJSCOPE_CLAUSE_RS][TERM_SCOPE_RS][$taxonomy]))) { //unset($scope_criteria[TERM_SCOPE_RS][$taxonomy]); // this doesn't affect anything (removed in v1.1) continue; } } } $terms = array_unique($terms); if ($qvars = $this->scoper->taxonomies->get_terms_query_vars($taxonomy)) { if ($terms_query && !$otype_use_object_roles) { $qtv = $this->scoper->taxonomies->get_terms_query_vars($taxonomy, true); $taxonomy_clauses[false][] = "{$qtv->term->alias}.{$qtv->term->col_id} IN ('" . implode("', '", $terms) . "') {$objscope_clause}"; } else { $this_tx_clause = "{$qvars->term->alias}.{$qvars->term->col_id} IN ('" . implode("', '", $terms) . "')"; // Use a subselect rather than adding our own LEFT JOIN. $terms_subselect = "SELECT {$qvars->term->alias}.{$qvars->term->col_obj_id} FROM {$qvars->term->table} {$qvars->term->as} WHERE {$this_tx_clause}"; if (defined('RVY_VERSION') && $objrole_revisions_clause) { $revision_clause = "OR ( {$src_table}.{$src->cols->type} = 'revision' AND {$src_table}.{$src->cols->parent} IN ( {$terms_subselect} ) )"; } else { $revision_clause = ''; } $taxonomy_clauses[$is_strict][] = "( {$src_table}.{$src->cols->id} IN ( {$terms_subselect} ) {$revision_clause} ) {$objscope_clause}"; } } } if ($taxonomy_clauses) { // all taxonomy clauses concat: [taxonomy 1 clauses] [OR] [taxonomy 2 clauses] [OR] ... //$where[$date_key][$objscope_clause][TERM_SCOPE_RS] = agp_implode(' ) OR ( ', $taxonomy_clauses, ' ( ', ' ) '); // strict taxonomy clauses (if any are present, they must all be satisfied) if (!empty($taxonomy_clauses[true])) { $where[$date_key][$objscope_clause][TERM_SCOPE_RS] = agp_implode(' ) AND ( ', $taxonomy_clauses[true], ' ( ', ' ) '); // non-strict taxonomy clauses } elseif (!empty($taxonomy_clauses[false])) { $where[$date_key][$objscope_clause][TERM_SCOPE_RS] = agp_implode(' ) OR ( ', $taxonomy_clauses[false], ' ( ', ' ) '); } else { $where[$date_key][$objscope_clause][TERM_SCOPE_RS] = '1=2'; } // all taxonomy clauses concat: ( [strict taxonomy clause 1] [AND] [strict taxonomy clause 2]... ) [OR] [taxonomy 3 clauses] [OR] ... //$where[$date_key][$objscope_clause][TERM_SCOPE_RS] = agp_implode(' ) OR ( ', $taxonomy_clauses, ' ( ', ' ) '); } break; case OBJECT_SCOPE_RS: // should only exist with nullstring objscope_clause if ($user_qualifies_for_obj_roles) { global $wpdb; $u_g_clause = $user->get_user_clause('uro'); foreach (array_keys($scope_criteria[OBJECT_SCOPE_RS]) as $role_type) { //should be only one if ($scope_criteria[OBJECT_SCOPE_RS][$role_type]) { ksort($scope_criteria[OBJECT_SCOPE_RS][$role_type]); } // sort array for efficient membuffering of query results // Combine all qualifying (and applied) object roles into a single OR clause $role_in = "'" . implode("', '", array_keys($scope_criteria[OBJECT_SCOPE_RS][$role_type])) . "'"; static $cache_obj_ids = array(); if ('post.php' == $GLOBALS['pagenow'] && !empty($_REQUEST['action']) || did_action('save_post') || !empty($_GET['doaction'])) { $force_refresh = true; } $objrole_subselect = "SELECT DISTINCT uro.obj_or_term_id FROM {$wpdb->user2role2object_rs} AS uro WHERE uro.role_type = '{$role_spec->role_type}' AND uro.scope = 'object' AND uro.assign_for IN ('entity', 'both') AND uro.role_name IN ({$role_in}) AND uro.src_or_tx_name = '{$src_name}' {$object_roles_duration_clause} {$u_g_clause} "; if (!isset($cache_obj_ids[$objrole_subselect]) || !empty($force_refresh)) { $cache_obj_ids[$objrole_subselect] = scoper_get_col($objrole_subselect); } if ($cache_obj_ids[$objrole_subselect]) { $where[$date_key][$objscope_clause][OBJECT_SCOPE_RS] = "{$src_table}.{$src->cols->id} IN ( '" . implode("','", $cache_obj_ids[$objrole_subselect]) . "' )"; } else { $where[$date_key][$objscope_clause][OBJECT_SCOPE_RS] = "1=2"; } if (defined('RVY_VERSION') && $objrole_revisions_clause) { $where[$date_key][$objscope_clause][OBJECT_SCOPE_RS] = "( {$where[$date_key][$objscope_clause]['object']} OR ( {$src_table}.{$src->cols->type} = 'revision' AND {$src_table}.{$src->cols->parent} IN ( '" . implode("','", $cache_obj_ids[$objrole_subselect]) . "' ) ) )"; } } } break; } // end scope switch } // end foreach scope /* // --- optional hack to require read_private cap via blog role AND object role if ( ! empty($require_blog_and_obj_role) ) { if ( ! isset($where[$date_key][''][BLOG_SCOPE_RS]) ) $where[$date_key][''][BLOG_SCOPE_RS] = '1=2'; if ( ! isset($where[$date_key][''][TERM_SCOPE_RS]) ) $where[$date_key][''][TERM_SCOPE_RS] = '1=2'; if ( ! isset($where[$date_key][''][OBJECT_SCOPE_RS]) ) $where[$date_key][''][OBJECT_SCOPE_RS] = '1=2'; $where[$date_key][''] = "( ( {$where[$date_key]['']['blog']} ) OR ( {$where[$date_key]['']['term']} ) ) AND ( {$where[$date_key]['']['object']} )"; } else // --- end hack */ // all scope clauses concat: [object roles] OR [term ids] OR [blogrole1 clause] [OR] [blogrole2 clause] [OR] ... // Collapse the array to a string even if it's empty $where[$date_key][$objscope_clause] = agp_implode(' ) OR ( ', $where[$date_key][$objscope_clause], ' ( ', ' ) '); } // end foreach objscope clause $date_clause = ''; if ($date_key && is_serialized($date_key)) { $content_date_limits = unserialize($date_key); if ($content_date_limits->content_min_date_gmt) { $date_clause .= " AND {$src_table}.{$src->cols->date} >= '" . $content_date_limits->content_min_date_gmt . "'"; } if ($content_date_limits->content_max_date_gmt) { $date_clause .= " AND {$src_table}.{$src->cols->date} <= '" . $content_date_limits->content_max_date_gmt . "'"; } } foreach (array_keys($where[$date_key]) as $objscope_clause) { if (empty($where[$date_key][$objscope_clause])) { unset($where[$date_key][$objscope_clause]); } } // all objscope clauses concat: [clauses w/o objscope] [OR] [objscope 1 clauses] [OR] [objscope 2 clauses] $where[$date_key] = agp_implode(' ) OR ( ', $where[$date_key], ' ( ', ' ) '); if ($date_clause && $where[$date_key]) { $where[$date_key] = "( {$where[$date_key]}{$date_clause} )"; } } // end foreach datekey (set of content date limits for which role(s) apply) foreach (array_keys($where) as $date_key) { if (empty($where[$date_key])) { unset($where[$date_key]); } } // all date clauses concat: [clauses w/o content date limits] [OR] [content date range 1 clauses] [OR] [content date range 2 clauses] $where = agp_implode(' ) OR ( ', $where, ' ( ', ' ) '); if (empty($where)) { $where = '1=2'; } return $where; }
function posts_teaser_prep_results($results, $tease_otypes, $args = '') { $defaults = array('user' => '', 'use_object_roles' => -1, 'use_term_roles' => -1, 'request' => '', 'object_type' => ''); $args = array_merge($defaults, (array) $args); extract($args); global $wpdb, $scoper, $wp_query; global $query_interceptor; if (did_action('wp_meta') && !did_action('wp_head')) { return $results; } if (empty($request)) { // TODO: teaser logs last_request itself global $query_interceptor; if (empty($query_interceptor->last_request['post'])) { // try to get it from wpdb instead if (!empty($wpdb->last_query)) { $request = $wpdb->last_query; } else { // don't risk exposing hidden content if something goes wrong with query logging return array(); } } else { $request = $query_interceptor->last_request['post']; } } // Pagination could be broken by subsequent query for filtered ids, so buffer current paging parameters // ( this code mimics WP_Query::get_posts() ) if (!empty($wp_query->query_vars['posts_per_page'])) { $found_posts_query = apply_filters('found_posts_query', 'SELECT FOUND_ROWS()'); $buffer_found_posts = $wpdb->get_var($found_posts_query); if ($buffer_found_posts >= $wp_query->query_vars['posts_per_page']) { $restore_pagination = true; $buffer_found_posts = apply_filters('found_posts', $buffer_found_posts); } } $list_private = array(); if (awp_ver('3.0')) { $private_stati = get_post_stati(array('private' => true)); } else { $private_stati = array('private'); } if (is_single() || is_page()) { $maybe_fudge_private = true; $maybe_strip_private = false; } else { $maybe_strip_private = true; $maybe_fudge_private = false; } if (!is_object($user)) { global $current_user; $user = $current_user; } // don't risk exposing hidden content if there is a problem with query parsing if (!($pos = strpos(strtoupper($request), " FROM"))) { return array(); } $distinct = stripos($request, " DISTINCT ") ? 'DISTINCT' : ''; // RS does not add any joins, but if DISTINCT clause exists in query, retain it $request = "SELECT {$distinct} {$wpdb->posts}.ID " . substr($request, $pos); if ($limitpos = strpos($request, ' LIMIT ')) { $request = substr($request, 0, $limitpos); } $args['skip_teaser'] = true; $filtered_request = $query_interceptor->flt_objects_request($request, 'post', $object_type, $args); global $scoper_teaser_filtered_ids; $scoper_teaser_filtered_ids = scoper_get_col($filtered_request); if (!isset($scoper->teaser_ids)) { $scoper->teaser_ids = array(); } $hide_ungranted_private = array(); foreach ($tease_otypes as $object_type) { $hide_ungranted_private[$object_type] = scoper_get_otype_option('teaser_hide_private', 'post', $object_type); } foreach (array_keys($results) as $key) { if (is_array($results[$key])) { $id = $results[$key]['ID']; } else { $id = $results[$key]->ID; } if (!$scoper_teaser_filtered_ids || !in_array($id, $scoper_teaser_filtered_ids)) { if (isset($results[$key]->post_type)) { $object_type = $results[$key]->post_type; } else { $object_type = $scoper->data_sources->get_from_db('type', 'post', $id); } if (!in_array($object_type, $tease_otypes)) { continue; } // Defeat a WP core secondary safeguard so we can apply the teaser message rather than 404 if (in_array($results[$key]->post_status, $private_stati)) { // don't want the teaser message (or presence in category archive listing) if we're hiding a page from listing $type_obj = get_post_type_object($object_type); if ($type_obj && $type_obj->hierarchical) { // TODO: review implementation of this option with custom types if (!isset($list_private[$object_type])) { $list_private[$object_type] = scoper_get_otype_option('private_items_listable', 'post', 'page'); } } else { $list_private[$object_type] = true; } if ($hide_ungranted_private[$object_type] || $maybe_strip_private && !$list_private[$object_type]) { $need_reindex = true; unset($results[$key]); // Actually, don't do this because the current method of removing private items from the paged result set will not move items from one result page to another //$buffer_found_posts--; // since we're removing this item from the teased results, decrement the paging total continue; } elseif (!empty($maybe_fudge_private) && $list_private[$object_type]) { $results[$key]->post_status = 'publish'; } } } } if (!empty($need_reindex)) { // re-index the array so paging isn't confused $results = array_values($results); } // pagination could be broken by the filtered ids query performed in this function, so original paging parameters were buffered if (!empty($restore_pagination)) { // WP query will apply found_posts filter shortly after this function returns. Feed it the buffered value from original unfiltered results. // Static flag in created function ensures it is only applied once. $func_name = create_function('$a', 'static $been_here; if ( ! empty($been_here) ) return $a; else {$been_here = true; ' . "return {$buffer_found_posts};}"); add_filter('found_posts', $func_name, 1); } return $results; }
function determine_role_usage_rs($src_name = 'post', $listed_ids = '') { global $scoper, $wpdb; if ('post' != $src_name) { return; } if (empty($listed_ids)) { if (!empty($scoper->listed_ids[$src_name])) { $listed_ids = $scoper->listed_ids[$src_name]; } else { return; } } if (empty($this->checked_ids[$src_name])) { $this->checked_ids[$src_name] = array(); } else { if (!array_diff_key($this->checked_ids[$src_name], $listed_ids)) { return; } } $this->checked_ids[$src_name] = $this->checked_ids[$src_name] + $listed_ids; $src = $scoper->data_sources->get($src_name); $col_id = $src->cols->id; $col_type = isset($src->cols->type) ? $src->cols->type : ''; if ($viewing_object_type = cr_find_post_type()) { $object_types = (array) $viewing_object_type; } else { $object_types = array_diff_key(get_post_types(array('public' => true)), array('attachment')); } // For now, only determine restricted posts if using RS role type. // Backing this out will be more convoluted for WP role type; may need to just list which roles are restricted rather than trying to give an Restricted Read/Edit summary $roles = array(); if (is_admin()) { foreach ($object_types as $_post_type) { $roles["edit"][$_post_type] = array("publish" => "rs_{$_post_type}_editor", "private" => "rs_{$_post_type}_editor", "draft" => "rs_{$_post_type}_contributor", "pending" => "rs_{$_post_type}_contributor", "future" => "rs_{$_post_type}_editor", "trash" => "rs_{$_post_type}_editor"); $roles["read"][$_post_type] = array("publish" => "rs_{$_post_type}_reader", "private" => "rs_private_{$_post_type}_reader", "draft" => "rs_{$_post_type}_reader", "pending" => "rs_{$_post_type}_reader", "future" => "rs_{$_post_type}_reader", "trash" => "rs_{$_post_type}_editor"); } } else { foreach ($object_types as $_post_type) { $roles["read"][$_post_type] = array("publish" => "rs_{$_post_type}_reader", "private" => "rs_private_{$_post_type}_reader"); } } // which of these results ignore blog role assignments? $uses_taxonomies = scoper_get_taxonomy_usage($src_name, $object_types); if (!empty($uses_taxonomies)) { foreach ($uses_taxonomies as $taxonomy) { $tx_object_types = $object_types; foreach ($tx_object_types as $key => $object_type) { // ignore term restrictions / roles for object types which have them disabled $_use_term_roles = scoper_get_otype_option('use_term_roles', $src_name, $object_type); if (empty($_use_term_roles[$taxonomy])) { unset($tx_object_types[$key]); } } if (!$tx_object_types) { continue; } if (!$scoper->taxonomies->is_member($taxonomy)) { continue; } $qvars = $scoper->taxonomies->get_terms_query_vars($taxonomy); $term_join = " INNER JOIN {$qvars->term->table} {$qvars->term->as} ON {$src->table}.{$src->cols->id} = {$qvars->term->alias}.{$qvars->term->col_obj_id} "; // ======== Log term restrictions ======== // if ($scoper->taxonomies->member_property($taxonomy, 'requires_term')) { if ($strict_terms = $scoper->get_restrictions(TERM_SCOPE_RS, $taxonomy)) { $this->any_restricted_terms = true; } $all_terms = $scoper->get_terms($taxonomy, UNFILTERED_RS, COL_ID_RS); foreach (array_keys($roles) as $op_type) { $status_where = array(); foreach ($tx_object_types as $object_type) { $term_clauses = array(); foreach ($roles[$op_type][$object_type] as $status => $check_role) { if (isset($strict_terms['restrictions'][$check_role]) && is_array($strict_terms['restrictions'][$check_role])) { $this_strict_terms = array_keys($strict_terms['restrictions'][$check_role]); } elseif (isset($strict_terms['unrestrictions'][$check_role]) && is_array($strict_terms['unrestrictions'][$check_role])) { $this_strict_terms = array_diff($all_terms, array_keys($strict_terms['unrestrictions'][$check_role])); } else { $this_strict_terms = array(); } if (!$this_strict_terms) { // no terms in this taxonomy have restricted roles $term_clauses[$status] = '1=2'; } elseif (count($this_strict_terms) < count($all_terms)) { // some (but not all) terms in this taxonomy honor blog-wide assignment of the pertinent role $term_clauses[$status] = " {$qvars->term->alias}.{$qvars->term->col_id} IN ('" . implode("', '", $this_strict_terms) . "')"; } else { $term_clauses[$status] = '1=1'; } if (isset($term_clauses[$status])) { $status_where[$object_type][$status] = " {$src->cols->status} = '{$status}' AND ( {$term_clauses[$status]} ) "; } } // end foreach statuses if (isset($status_where[$object_type])) { // object_type='type_val' AND ( (status 1 clause) OR (status 2 clause) ... $status_where[$object_type] = " {$src->cols->type} = '{$object_type}' AND ( " . agp_implode(' ) OR ( ', $status_where[$object_type], ' ( ', ' ) ') . " )"; } } // end foreach tx_object_types // NOTE: we are querying for posts/pages which HAVE restrictions that apply to their current post_status // if ($status_where) { // (object type 1 clause) OR (object type 2 clause) ... $where = ' AND (' . agp_implode(' ) OR ( ', $status_where, ' ( ', ' ) ') . ' )'; $where .= " AND {$src->table}.{$col_id} IN ('" . implode("', '", array_keys($listed_ids)) . "')"; $query = "SELECT DISTINCT {$col_id} FROM {$src->table} {$term_join} WHERE 1=1 {$where}"; if (isset($query_results[$query])) { $restricted_ids = $query_results[$query]; } else { $restricted_ids = scoper_get_col($query); $query_results[$query] = $restricted_ids; } foreach ($restricted_ids as $id) { $this->termscoped_ids[$src_name][$id][$op_type] = true; $this->restricted_ids[$src_name][$id][$op_type] = true; } } } // end foreach op_type (read/edit) } // end term restrictions logging // ======== Log term roles ======== // if (is_admin() && !empty($qvars)) { if ($src_roles = $scoper->role_defs->get_matching('rs', 'post', $tx_object_types)) { $otype_role_names = array(); foreach (array_keys($src_roles) as $role_handle) { $otype_role_names[] = $src_roles[$role_handle]->name; } $role_clause = "AND uro.role_name IN ('" . implode("', '", $otype_role_names) . "')"; $join_assigned = $term_join . " INNER JOIN {$wpdb->user2role2object_rs} AS uro ON uro.obj_or_term_id = {$qvars->term->alias}.{$qvars->term->col_id}" . " AND uro.scope = 'term' AND uro.role_type = 'rs' {$role_clause} AND uro.src_or_tx_name = '{$taxonomy}'"; $where = " AND {$src->table}.{$col_id} IN ('" . implode("', '", array_keys($listed_ids)) . "')"; $query = "SELECT DISTINCT {$col_id}, uro.role_name FROM {$src->table} {$join_assigned} WHERE 1=1 {$where}"; $role_results = scoper_get_results($query); foreach ($role_results as $row) { $role_handle = scoper_get_role_handle($row->role_name, 'rs'); $this->have_termrole_ids[$src_name][$row->{$col_id}][$role_handle] = true; } } } // end term roles logging } // end foreach of this data source's taxonomies } // endif this data source uses taxonomies // which of these results ignore blog AND term role assignments? if ($objscope_objects = $scoper->get_restrictions(OBJECT_SCOPE_RS, $src_name)) { $this->any_restricted_objects = true; } foreach (array_keys($roles) as $op_type) { foreach ($object_types as $object_type) { if (!scoper_get_otype_option('use_object_roles', $src_name, $object_type)) { continue; } if (is_array($roles[$op_type][$object_type])) { foreach (array_keys($listed_ids) as $id) { foreach ($roles[$op_type][$object_type] as $check_role) { // If a restriction is set for this object and role, // OR if the role is default-restricted with no unrestriction for this object... if (isset($objscope_objects['restrictions'][$check_role][$id]) || isset($objscope_objects['unrestrictions'][$check_role]) && is_array($objscope_objects['unrestrictions'][$check_role]) && !isset($objscope_objects['unrestrictions'][$check_role][$id])) { $this->objscoped_ids[$src_name][$id][$op_type] = true; $this->restricted_ids[$src_name][$id][$op_type] = true; } } } //end foreach listed ids } // endif any applicable roles defined } // end forach object type } // end foreach op_type (read/edit) // query for object role assignments if (is_admin()) { if ($scoper->get_applied_object_roles()) { //$this->any_object_roles = true; $join_assigned = " INNER JOIN {$wpdb->user2role2object_rs} AS uro ON uro.obj_or_term_id = {$src->table}.{$col_id}" . " AND uro.src_or_tx_name = '{$src_name}' AND uro.scope = 'object' AND uro.role_type = 'rs'"; $where = " AND {$src->table}.{$col_id} IN ('" . implode("', '", array_keys($listed_ids)) . "')"; $query = "SELECT DISTINCT {$col_id}, uro.role_name FROM {$src->table} {$join_assigned} WHERE 1=1 {$where}"; $role_results = scoper_get_results($query); foreach ($role_results as $row) { $role_handle = scoper_get_role_handle($row->role_name, 'rs'); $this->have_objrole_ids[$src_name][$row->{$col_id}][$role_handle] = true; //$this->any_object_roles = true; } } } }
function _flt_user_has_cap($wp_blogcaps, $orig_reqd_caps, $args) { // =============================== STATIC VARIABLE DECLARATION AND INITIALIZATION (to memcache filtering results) ===== static $cache_tested_ids; static $cache_okay_ids; static $cache_where_clause; if (empty($cache_tested_ids)) { $cache_where_clause = array(); $cache_tested_ids = array(); $cache_okay_ids = array(); } // ==================================================================================================================== // =============================================== TEMPORARY DEBUG CODE ================================================ //dump($orig_reqd_caps); //dump($args); //if ( strpos( $_SERVER['REQUEST_URI'], 'ajax' ) ) { //if ( ! empty($_REQUEST) ) // rs_errlog( serialize($_REQUEST) ); //rs_errlog( '' ); //rs_errlog('flt_user_has_cap'); //rs_errlog(serialize($orig_reqd_caps)); //rs_errlog(serialize($args)); //rs_errlog(''); //} // ============================================= (end temporary debug code) ============================================== // convert 'rs_role_name' to corresponding caps (and also make a tinkerable copy of orig_reqd_caps) $orig_reqd_caps = $this->scoper->role_defs->role_handles_to_caps($orig_reqd_caps); // ================= EARLY EXIT CHECKS (if the provided reqd_caps do not need filtering or need special case filtering ================== global $pagenow; // Disregard caps which are not defined in Role Scoper config if (!($rs_reqd_caps = array_intersect($orig_reqd_caps, $this->scoper->cap_defs->get_all_keys()))) { return $wp_blogcaps; } // log initial set of RS-filtered caps (in case we swap in equivalent caps for intermediate processing) $orig_reqd_caps = $rs_reqd_caps; // permitting this filter to execute early in an attachment request resets the found_posts record, preventing display in the template if (is_attachment() && !is_admin() && !did_action('template_redirect')) { if (empty($GLOBALS['scoper_checking_attachment_access'])) { return $wp_blogcaps; } } // work around bug in mw_EditPost method (requires publish_pages AND publish_posts cap) if (defined('XMLRPC_REQUEST') && 'publish_posts' == $orig_reqd_caps[0]) { if (!empty($GLOBALS['xmlrpc_post_type_rs']) && 'page' == $GLOBALS['xmlrpc_post_type_rs']) { return array('publish_posts' => true); } } // backdoor to deal with rare cases where one of the caps included in RS role defs cannot be filtered properly if (defined('UNSCOPED_CAPS_RS') && !array_diff($orig_reqd_caps, explode(',', UNSCOPED_CAPS_RS))) { return $wp_blogcaps; } // custom workaround to reveal all private / restricted content in all blogs if logged into main blog if (defined('SCOPER_MU_MAIN_BLOG_RULES')) { include_once dirname(__FILE__) . '/mu-custom.php'; if (!array_diff($orig_reqd_caps, array('read', 'read_private_pages', 'read_private_posts'))) { if ($return_caps = ScoperMU_Custom::current_user_logged_into_main($wp_blogcaps, $orig_reqd_caps)) { return $return_caps; } } } //define( 'SCOPER_NO_COMMENT_FILTERING', true ); if (defined('SCOPER_NO_COMMENT_FILTERING') && 'moderate_comments' == $orig_reqd_caps[0] && empty($GLOBALS['current_rs_user']->allcaps['moderate_comments'])) { return $wp_blogcaps; } if (defined('SCOPER_ALL_UPLOADS_EDITABLE') && $pagenow == 'upload.php' && in_array($orig_reqd_caps[0], array('upload_files', 'edit_others_posts', 'delete_others_posts'))) { return $wp_blogcaps; } // =================================================== (end early exit checks) ====================================================== // ============================ GLOBAL VARIABLE DECLARATIONS, ARGUMENT TRANSLATION AND STATUS DETECTION ============================= global $current_rs_user; $user_id = isset($args[1]) ? $args[1] : 0; if ($user_id && $user_id != $current_rs_user->ID) { $user = rs_get_user($user_id); } else { $user = $current_rs_user; } // currently needed for filtering async-upload.php if (empty($user->blog_roles) || empty($user->blog_roles[''])) { $this->scoper->refresh_blogroles(); } $object_id = isset($args[2]) ? (int) $args[2] : 0; // WP passes comment ID with 'edit_comment' metacap if ($object_id && 'edit_comment' == $args[0]) { if (!in_array('moderate_comments', $rs_reqd_caps)) { // as of WP 3.2.1, 'edit_comment' maps to related post's 'edit_post' caps without requiring moderate_comments if (scoper_get_option('require_moderate_comments_cap')) { $rs_reqd_caps[] = 'moderate_comments'; $modified_caps = true; } } if ($comment = get_comment($object_id)) { $object_id = $comment->comment_post_ID; } else { $object_id = 0; } } // note the data source and object type(s) which are associated with the required caps (based on inclusion in RS Role Definitions) $is_taxonomy_cap = false; $src_name = ''; $cap_types = $this->scoper->cap_defs->src_otypes_from_caps($rs_reqd_caps, $src_name); // note: currently only needed for src_name determination $doing_admin_menus = is_admin() && (did_action('_admin_menu') && !did_action('admin_menu') || did_action('admin_head') && !did_action('adminmenu')); // for scoped menu management roles, satisfy edit_theme_options cap requirement if (array_key_exists(0, $orig_reqd_caps) && 'edit_theme_options' == $orig_reqd_caps[0] && empty($wp_blogcaps['edit_theme_options'])) { if (in_array($GLOBALS['pagenow'], array('nav-menus.php', 'admin-ajax.php')) || $doing_admin_menus) { $key = array_search('edit_theme_options', $rs_reqd_caps); if (false !== $key) { $tx = get_taxonomy('nav_menu'); $rs_reqd_caps[$key] = $tx->cap->manage_terms; $src_name = 'nav_menu'; // menu-specific manager assignment does not permit deletion of the menu if (!empty($_REQUEST['action']) && 'delete' == $_REQUEST['action']) { $this->skip_any_term_check = true; } } } } if (!$src_name) { // required capabilities correspond to multiple data sources return $wp_blogcaps; } // slight simplification: assume a single cap object type for a few cap substitution checks $is_taxonomy_cap = $this->scoper->cap_defs->member_property(reset($rs_reqd_caps), 'is_taxonomy_cap'); // Establish some context by detecting object type - based on object ID if provided, or otherwise based on http variables. if (in_array($pagenow, array('media-upload.php', 'async-upload.php'))) { if (!empty($GLOBALS['post'])) { $object_type = $GLOBALS['post']->post_type; } } elseif (is_admin() && 'edit-tags.php' == $GLOBALS['pagenow'] && 'link_category' == $_REQUEST['taxonomy']) { $src_name = 'link'; $object_type = 'link_category'; } elseif (array_key_exists(0, $orig_reqd_caps) && in_array($orig_reqd_caps[0], array('manage_nav_menus', 'edit_theme_options'))) { $src_name = 'nav_menu'; } if (empty($object_type)) { $object_type = cr_find_object_type($src_name, $object_id); } $object_type_obj = cr_get_type_object($src_name, $object_type); $is_att_rev = false; if ('post' == $src_name) { if (in_array($object_type, array('attachment', 'revision'))) { $is_att_rev = true; if ($object_id) { if ($_post = get_post($object_id)) { if ($_parent = get_post($_post->post_parent)) { $object_type = $_parent->post_type; $object_id = $_parent->ID; // deal with case of edit_posts cap check on attachments to revision (with Revisionary) if ('revision' == $object_type) { if ($_orig_post = get_post($_parent->post_parent)) { $object_type = $_orig_post->post_type; $object_id = $_orig_post->ID; } } $object_type_obj = get_post_type_object($object_type); } } } } elseif (!$is_taxonomy_cap) { $use_post_types = scoper_get_option('use_post_types'); if (empty($use_post_types[$object_type])) { return $wp_blogcaps; } } } // ===================================================================================================================================== // ======================================== SUBVERT MISGUIDED CAPABILITY REQUIREMENTS ================================================== if ('post' == $src_name) { if (!$is_taxonomy_cap) { $modified_caps = false; if ('post' != $object_type) { $replace_post_caps = array('publish_posts', 'edit_others_posts', 'edit_published_posts'); // Replace edit_posts requirement with corresponding type-specific requirement, but only after admin menu is drawn, or on a submission before the menu is drawn if (did_action('admin_init')) { // otherwise extra padding between menu items due to some items populated but unpermitted $replace_post_caps[] = 'edit_posts'; } if (in_array($pagenow, array('upload.php', 'media.php'))) { $replace_post_caps = array_merge($replace_post_caps, array('delete_posts', 'delete_others_posts')); } foreach ($replace_post_caps as $post_cap_name) { $key = array_search($post_cap_name, $rs_reqd_caps); if (false !== $key && !$doing_admin_menus && in_array($pagenow, array('edit.php', 'post.php', 'post-new.php', 'press-this.php', 'admin-ajax.php', 'upload.php', 'media.php'))) { $rs_reqd_caps[$key] = $object_type_obj->cap->{$post_cap_name}; $modified_caps = true; } } } // WP core quirk workaround: edit_others_posts is required as preliminary check for populating authors dropdown for any post type. Instead, we need to do our own validation based on scoped roles. // (but don't mess if this cap requirement is part of an edit_post metacap check for a specific post) if (!$object_id && count($rs_reqd_caps) == 1) { if (in_array(reset($rs_reqd_caps), array('edit_others_posts'))) { require_once dirname(__FILE__) . '/lib/agapetry_wp_admin_lib.php'; // function awp_metaboxes_started() if (!awp_metaboxes_started($object_type) && 'revision.php' != $pagenow && 'revisions' != $GLOBALS['plugin_page_cr']) { // don't enable contributors to view/restore revisions $rs_reqd_caps[0] = $object_type_obj->cap->edit_posts; } else { $rs_reqd_caps[0] = $object_type_obj->cap->edit_published_posts; } // we will filter / suppress the author dropdown downstream from here $modified_caps = true; } } // as of WP 3.1, addition of new nav menu items requires edit_posts capability (otherwise nav menu item is orphaned with no menu relationship) if (is_admin() && strpos($_SERVER['SCRIPT_NAME'], 'nav-menus.php')) { if ('edit_posts' == $orig_reqd_caps[0]) { $type_obj = get_taxonomy('nav_menu'); $rs_reqd_caps[0] = $type_obj->cap->manage_terms; $modified_caps = true; } } } // endif not taxonomy cap } // endif caps correspond to 'post' data source //====================================== (end subvert misguided capability requirements) ============================================= if (defined('RVY_VERSION')) { require_once dirname(__FILE__) . '/revisionary-helper_rs.php'; $rs_reqd_caps = Rvy_Helper::convert_post_edit_caps($rs_reqd_caps, $object_type); } //rs_errlog( "matched context for $object_id : $matched_context" ); // don't apply object-specific filtering for auto-drafts if ('post' == $src_name) { if ($object_id) { if ($_post = get_post($object_id)) { if ('auto-draft' == $_post->post_status) { // && ! empty($_POST['action']) ) $object_id = 0; if (!$doing_admin_menus) { $this->skip_id_generation = true; } } } } else { if (!empty($GLOBALS['post']) && !is_object($GLOBALS['post'])) { $GLOBALS['post'] = get_post($GLOBALS['post']); } if (!empty($GLOBALS['post']) && 'auto-draft' == $GLOBALS['post']->post_status && !$doing_admin_menus) { $this->skip_id_generation = true; } } } //dump($object_id); // If no object id was passed in... if (!$object_id) { // || ! $matched_context ) { //if ( $missing_caps = array_diff($rs_reqd_caps, array_keys($wp_blogcaps) ) ) { if (!$doing_admin_menus) { if (!empty($_REQUEST['action']) && in_array($pagenow, array('edit.php', 'edit-tags.php'))) { $this->skip_id_generation = true; } // ============================================ OBJECT ID DETERMINATION ======================================== if (!$this->skip_id_generation && !defined('XMLRPC_REQUEST') && !in_array($pagenow, array('media-upload.php', 'async-upload.php'))) { // lots of superfluous queries in media upload popup otherwise // Try to generate missing object_id argument for problematic current_user_can calls static $generated_id; if (!isset($generated_id)) { $generated_id = array(); } // if the id was not already detected and stored to the static variable... $caps_key = serialize($rs_reqd_caps); if (!isset($generated_id[$object_type][$caps_key])) { $gen_id = 0; foreach ($rs_reqd_caps as $cap_name) { if ($gen_id = (int) $this->_detect_object_id($cap_name)) { break; // means we are accepting the generated id } } $generated_id[$object_type][$caps_key] = $gen_id; $object_id = $gen_id; } else { $object_id = $generated_id[$object_type][$caps_key]; } //rs_errlog( "detected ID: $object_id" ); } else { $this->skip_id_generation = false; } // this is a one-time flag // ========================================= (end object id determination) ======================================= } // If we still have no object id (detection was skipped or failed to identify it)... if (!$object_id) { // || ! $matched_context ) { // ============================================ "CAN FOR ANY" CHECKS =========================================== if ($missing_caps = array_diff($rs_reqd_caps, array_keys($wp_blogcaps))) { // These checks are only relevant since no object_id was provided. Otherwise (in the main body of this function), taxonomy and object caps will be credited via scoped query. // If we are about to fail the blogcap requirement, credit a missing cap if the user has it by term role for ANY term. // This prevents failing initial UI entrance exams that only consider blog-wide roles. if (!$this->skip_any_term_check) { if ($tax_caps = $this->user_can_for_any_term($missing_caps)) { $wp_blogcaps = array_merge($wp_blogcaps, $tax_caps); } //rs_errlog( "can for any term: " . serialize($tax_caps) ); } else { $this->skip_any_term_check = false; } // this is a one-time flag // If we are still missing required caps, credit a missing scoper-defined cap if the user has it by object role for ANY object. // (i.e. don't bar user from "Edit Pages" if they have edit_pages cap for at least one page) if ($missing_caps = array_diff($rs_reqd_caps, array_keys($wp_blogcaps))) { // prevent object-specific editing roles from allowing new object creation w/o sitewide capability $add_new_check = strpos($_SERVER['SCRIPT_NAME'], 'post-new.php') && 'post' == $src_name && reset($rs_reqd_caps) == $object_type_obj->cap->edit_posts; if (!$this->skip_any_object_check && !$add_new_check) { //if ( ! $this->skip_any_object_check ) { if ($object_caps = $this->user_can_for_any_object($missing_caps)) { $wp_blogcaps = array_merge($wp_blogcaps, $object_caps); } //rs_errlog( "can for any object: " . serialize($object_caps) ); } else { $this->skip_any_object_check = false; } // this is a one-time flag } } // ========================================== (end "can for any" checks ) ========================================= //rs_errlog( serialize( $wp_blogcaps) ); if ($missing_caps = array_diff($rs_reqd_caps, array_keys($wp_blogcaps))) { // normal exit point when no object ID is passed or detected, or when detected object type does not match required capabilities return $wp_blogcaps; } else { if ($restore_caps = array_diff($orig_reqd_caps, $rs_reqd_caps)) { // restore original reqd_caps which we substituted for the type-specific scoped query $wp_blogcaps = array_merge($wp_blogcaps, array_fill_keys($restore_caps, true)); } return $wp_blogcaps; } } //} else //return $wp_blogcaps; } if ($object_id && 'post' == $src_name) { $_post = get_post($object_id); $object_type = $_post->post_type; $object_type_obj = cr_get_type_object($src_name, $object_type); if (defined('RVY_VERSION') && in_array($pagenow, array('edit.php', 'edit-tags.php', 'admin-ajax.php')) && (!empty($_REQUEST['action']) && -1 != $_REQUEST['action'])) { $rs_reqd_caps = Rvy_Helper::fix_table_edit_reqd_caps($rs_reqd_caps, $args[0], $_post, $object_type_obj); } // if the top level page structure is locked, don't allow non-administrator to delete a top level page either if ('page' == $object_type || defined('SCOPER_LOCK_OPTION_ALL_TYPES') && !is_content_administrator_rs()) { $delete_metacap = !empty($object_type_obj->hierarchical) ? $object_type_obj->cap->delete_post : 'delete_page'; // if the top level page structure is locked, don't allow non-administrator to delete a top level page either if ($delete_metacap == $args[0]) { if ('1' === scoper_get_option('lock_top_pages')) { // stored value of 1 means only Administrators are allowed to modify top-level page structure if ($page = get_post($args[2])) { if (empty($page->post_parent)) { $in_process = false; return false; } } } } } } // Note: At this point, we have a nonzero object_id... // if this is a term administration request, route to user_can_admin_terms() if ($is_taxonomy_cap) { if ('post' == $src_name) { $cap_otype_obj = get_taxonomy($object_type); } if (('post' != $src_name || $cap_otype_obj && $rs_reqd_caps[0] == $cap_otype_obj->cap->manage_terms) && count($rs_reqd_caps) == 1) { // don't re-route if multiple caps are being required // always pass through any assigned blog caps which will not be involved in this filtering $rs_reqd_caps = array_fill_keys($rs_reqd_caps, 1); $undefined_reqd_caps = array_diff_key($wp_blogcaps, $rs_reqd_caps); require_once dirname(__FILE__) . '/admin/permission_lib_rs.php'; if (user_can_admin_terms_rs($object_type, $object_id, $user)) { return array_merge($undefined_reqd_caps, $rs_reqd_caps); } else { return $undefined_reqd_caps; // required caps we scrutinized are excluded from this array } } } // Workaround to deal with WP core's checking of publish cap prior to storing categories // Store terms to DB in advance of any cap-checking query which may use those terms to qualify an operation if (!empty($_REQUEST['action']) && (in_array($_REQUEST['action'], array('editpost', 'post')) || 'autosave' == $_REQUEST['action'])) { if (array_intersect(array('publish_posts', 'edit_posts', $object_type_obj->cap->publish_posts, $object_type_obj->cap->edit_posts), $rs_reqd_caps)) { $uses_taxonomies = scoper_get_taxonomy_usage($src_name, $object_type); static $inserted_terms; if (!isset($inserted_terms)) { $inserted_terms = array(); } foreach ($uses_taxonomies as $taxonomy) { // TODO: only if tx->requires_term is true? if (isset($inserted_terms[$taxonomy][$object_id])) { continue; } $inserted_terms[$taxonomy][$object_id] = true; //if ( $stored_terms = wp_get_object_terms( $object_id, $taxonomy ) ) // note: this will cause trouble if WP core ever auto-stores object terms on post creation // continue; $stored_terms = $this->scoper->get_terms($taxonomy, UNFILTERED_RS, COL_ID_RS, $object_id); require_once dirname(__FILE__) . '/admin/filters-admin-save_rs.php'; $selected_terms = cr_get_posted_object_terms($taxonomy); if (is_array($selected_terms)) { // non-hierarchical terms do not need to be pre-inserted if ($set_terms = $GLOBALS['scoper_admin_filters']->flt_pre_object_terms($selected_terms, $taxonomy)) { $set_terms = array_unique(array_map('intval', $set_terms)); if ($set_terms != $stored_terms && $set_terms && $set_terms != array(1)) { // safeguard against unintended clearing of stored categories wp_set_object_terms($object_id, $set_terms, $taxonomy); // delete any buffered cap check results which were queried prior to storage of these object terms unset($cache_tested_ids); unset($cache_where_clause); unset($cache_okay_ids); } } } } // also avoid chicken-egg situation when publish cap is granted by a propagating page role if ($object_type_obj->hierarchical && isset($_POST['parent_id'])) { if ($_POST['parent_id'] != get_post_field('post_parent', $object_id)) { global $wpdb; $set_parent = $GLOBALS['scoper_admin_filters']->flt_page_parent($_POST['parent_id']); $GLOBALS['wpdb']->query("UPDATE {$wpdb->posts} SET post_parent = '{$set_parent}' WHERE ID = '{$object_id}'"); require_once dirname(__FILE__) . '/admin/filters-admin-save_rs.php'; scoper_inherit_parent_roles($object_id, OBJECT_SCOPE_RS, $src_name, $set_parent, $object_type); scoper_inherit_parent_restrictions($object_id, OBJECT_SCOPE_RS, $src_name, $set_parent, $object_type); } } } } // generate a string key for this set of required caps, for use below in checking, caching the scoped results $arg_append = ''; $arg_append .= !empty($this->require_full_object_role) ? '-require_full_object_role-' : ''; $arg_append .= !empty($GLOBALS['revisionary']->skip_revision_allowance) ? '-skip_revision_allowance-' : ''; sort($rs_reqd_caps); $capreqs_key = implode($rs_reqd_caps) . $arg_append; // see ScoperAdmin::user_can_admin_object // ================================ SPECIAL HANDLING FOR ATTACHMENTS AND REVISIONS ========================================== $maybe_revision = 'post' == $src_name && !isset($cache_tested_ids[$src_name][$object_type][$capreqs_key][$object_id]); $maybe_attachment = in_array($pagenow, array('upload.php', 'media.php')); if ($maybe_revision || $maybe_attachment) { global $wpdb; if ($_post = get_post($object_id)) { if ('revision' == $_post->post_type) { require_once dirname(__FILE__) . '/lib/revisions_lib_rs.php'; $rev_where = defined('RVY_VERSION') && rvy_get_option('revisor_lock_others_revisions') ? " AND post_author = '{$current_rs_user->ID}'" : ''; // might need to apply different cap requirement for other users' revisions. todo: skip this clause for sitewide editors $revisions = rs_get_post_revisions($_post->post_parent, 'inherit', array('fields' => constant('COL_ID_RS'), 'return_flipped' => true, 'where' => $rev_where)); } if ('revision' == $_post->post_type || 'attachment' == $_post->post_type) { $is_att_rev = true; if ($_post->post_parent) { $object_id = $_post->post_parent; if ($_parent = get_post($_post->post_parent)) { $object_type = $_parent->post_type; $object_type_obj = get_post_type_object($object_type); } } elseif ('attachment' == $_post->post_type) { // special case for unattached uploads: uploading user should have their way with them if ($_post->post_author == $current_rs_user->ID) { $rs_reqd_caps[0] = 'read'; if ($restore_caps = array_diff($orig_reqd_caps, array_keys($rs_reqd_caps))) { // restore original reqd_caps which we substituted for the type-specific scoped query $wp_blogcaps = array_merge($wp_blogcaps, array_fill_keys($restore_caps, true)); } } return $wp_blogcaps; } } //endif retrieved post is a revision or attachment } // endif post retrieved } // endif specified id might be a revision or attachment if ($is_att_rev) { if ('post' != $object_type_obj->name) { // Compensate for WP's requirement of posts cap for attachment editing, regardless of whether it's attached to a post or page if ('edit_others_posts' == $rs_reqd_caps[0]) { $rs_reqd_caps[0] = $object_type_obj->cap->edit_others_posts; } elseif ('delete_others_posts' == $rs_reqd_caps[0]) { $rs_reqd_caps[0] = $object_type_obj->cap->delete_others_posts; } elseif ('edit_posts' == $rs_reqd_caps[0]) { $rs_reqd_caps[0] = $object_type_obj->cap->edit_posts; } elseif ('delete_posts' == $rs_reqd_caps[0]) { $rs_reqd_caps[0] = $object_type_obj->cap->delete_posts; } } } //endif retrieved post is a revision or attachment // ============================== (end special handling for attachments and revisions) ========================================== // ============ SCOPED QUERY for required caps on object id (if other listed ids are known, query for them also). Cache results to static var. =============== // $force_refresh = 'async-upload.php' == $pagenow; // Page refresh following publishing of new page by users who can edit by way of Term Role fails without this workaround if (!empty($_POST) && (defined('SCOPER_CACHE_SAFE_MODE') || in_array($pagenow, array('post.php', 'press-this.php')) && $args[0] == $object_type_obj->cap->edit_post)) { $force_refresh = true; $cache_tested_ids = array(); $cache_okay_ids = array(); $cache_where_clause = array(); } else { $force_refresh = false; } // Check whether this object id was already tested for the same reqd_caps in a previous execution of this function within the same http request if ($force_refresh || !isset($cache_tested_ids[$src_name][$object_type][$capreqs_key][$object_id])) { //if ( ! isset($cache_tested_ids[$src_name][$object_type][$capreqs_key][$object_id]) ) { // retrieve CR_Data_Source object, which contains database column names $src_table = $this->scoper->data_sources->member_property($src_name, 'table'); $cols = $this->scoper->data_sources->member_property($src_name, 'cols'); // Before querying for caps on this object, check whether we have a record of other posts listed alongside it. // If so, run the scoped query for ALL listed objects in that buffer, and buffer the results to static variable hascap_object_ids. // // (This is useful when front end code must check caps for each post // to determine whether to display 'edit' link, etc.) if (is_admin() && 'index.php' == $pagenow) { // there's too much happening on the dashboard (and too much low-level query filtering) to buffer listed IDs reliably. $listed_ids = array(); } else { if (isset($this->scoper->listed_ids[$src_name])) { $listed_ids = array_keys($this->scoper->listed_ids[$src_name]); } else { // note: don't use wp_object_cache because it includes posts not present in currently displayed resultset listing page $listed_ids = array(); } } // make sure our current object_id is in the list $listed_ids[] = $object_id; // since the objects_where_role_clauses() output itself is not id-specific, also statically buffer it per reqd_caps if ($force_refresh || !isset($cache_where_clause[$src_name][$object_type][$capreqs_key])) { $check_otype = 'link_category' == $object_type ? 'link' : $object_type; $use_term_roles = scoper_get_otype_option('use_term_roles', $src_name, $check_otype); $no_object_roles = $this->scoper->data_sources->member_property($src_name, 'no_object_roles'); $use_object_roles = $no_object_roles ? false : scoper_get_otype_option('use_object_roles', $src_name, $object_type); $this_args = array('object_type' => $object_type, 'user' => $user, 'otype_use_term_roles' => $use_term_roles, 'otype_use_object_roles' => $use_object_roles, 'skip_teaser' => true, 'require_full_object_role' => !empty($this->require_full_object_role)); //rs_errlog( serialize($rs_reqd_caps) ); //rs_errlog( serialize($this_args) ); $where = $this->query_interceptor->objects_where_role_clauses($src_name, $rs_reqd_caps, $this_args); if ($where) { $where = "AND ( {$where} )"; } // update static variable $cache_where_clause[$src_name][$object_type][$capreqs_key] = $where; } else { $where = $cache_where_clause[$src_name][$object_type][$capreqs_key]; } // run the query $query = "SELECT {$src_table}.{$cols->id} FROM {$src_table} WHERE 1=1 {$where} AND {$src_table}.{$cols->id} IN ('" . implode("', '", array_unique($listed_ids)) . "')"; if (isset($cache_okay_ids[$query])) { $okay_ids = $cache_okay_ids[$query]; } else { if ($okay_ids = scoper_get_col($query)) { $okay_ids = array_fill_keys($okay_ids, true); } } //dump($rs_reqd_caps); //dump($query); //dump($okay_ids); //rs_errlog( $query ); //rs_errlog( 'results: ' . serialize( $okay_ids ) ); // update static cache_tested_ids to log scoped results for this object id, and possibly also for other listed IDs if (empty($_GET['doaction']) || 'delete_post' != $args[0] && $object_type_obj->cap->delete_post != $args[0]) { // bulk post/page deletion is broken by hascap buffering foreach ($listed_ids as $_id) { $cache_tested_ids[$src_name][$object_type][$capreqs_key][$_id] = isset($okay_ids[$_id]); } $cache_okay_ids[$query] = $okay_ids; } $this_id_okay = isset($okay_ids[$object_id]); } else { // results of this same has_cap inquiry are already stored (from another call within current http request) $this_id_okay = $cache_tested_ids[$src_name][$object_type][$capreqs_key][$object_id]; } //rs_errlog( "okay ids: " . serialize( $okay_ids ) ); // if we redirected the cap check to revision parent, also credit all the revisions for passing results if ($this_id_okay && !empty($revisions)) { if (empty($_GET['doaction']) || 'delete_post' != $args[0] && $object_type_obj->cap->delete_post != $args[0]) { // bulk post/page deletion is broken by hascap buffering $cache_tested_ids[$src_name][$object_type][$capreqs_key] = $cache_tested_ids[$src_name][$object_type][$capreqs_key] + array_fill_keys($revisions, true); } } $rs_reqd_caps = array_fill_keys($rs_reqd_caps, true); if (!$this_id_okay) { if (array_key_exists(0, $orig_reqd_caps) && 'edit_posts' == $orig_reqd_caps[0] && strpos($_SERVER['REQUEST_URI'], 'async-upload.php')) { // temp workaround for ACF with Revisionary return $wp_blogcaps; } // ================= TEMPORARY DEBUG CODE =================== //d_echo("object_id $object_id FAILED !!!!!!!!!!!!!!!!!" ); //rs_errlog( "object_id $object_id FAILED !!!!!!!!!!!!!!!!!" ); //rs_errlog(serialize($orig_reqd_caps)); //rs_errlog(serialize($rs_reqd_caps)); //rs_errlog(''); /* $log .= "checked caps: " . serialize($rs_reqd_caps) . "\r\n"; $log .= "object_id $object_id FAILED !!!!!!!!!!!!!!!!!\r\n"; $log .= $query; rs_errlog( "\r\n{$log}\r\n" ); */ //d_echo( "FAILED for " . serialize($rs_reqd_caps) ); // ============== (end temporary debug code ================== return array_diff_key($wp_blogcaps, $rs_reqd_caps); // required caps we scrutinized are excluded from this array } else { if ($restore_caps = array_diff($orig_reqd_caps, array_keys($rs_reqd_caps))) { // restore original reqd_caps which we substituted for the type-specific scoped query $rs_reqd_caps = $rs_reqd_caps + array_fill_keys($restore_caps, true); } //d_echo( 'OKAY:' ); //dump($args); //dump($rs_reqd_caps); //d_echo( '<br />' ); return array_merge($wp_blogcaps, $rs_reqd_caps); } }
function scoper_attach_linked_uploads($echo = false) { global $wpdb; require_once SCOPER_ABSPATH . '/uploads_rs.php'; if (MULTISITE) { global $wpdb, $blog_id; $blog_ids = scoper_get_col("SELECT blog_id FROM {$wpdb->blogs} ORDER BY blog_id"); $orig_blog_id = $blog_id; } else { $blog_ids = array('1'); } foreach ($blog_ids as $id) { if (count($blog_ids) > 1) { switch_to_blog($id); _e("<br /><strong>site {$id} :</strong><br />"); } $uploads = scoper_get_upload_info(); $site_url = untrailingslashit(get_option('siteurl')); if (false === strpos($uploads['baseurl'], $site_url)) { if ($echo) { _e('<strong>Note</strong>: Direct access to uploaded file attachments cannot be filtered because your WP_CONTENT_DIR is not in the WordPress branch.', 'scoper'); echo '<br /><br />'; _e('The operation was terminated due to an invalid configuration.', 'scoper'); } return false; } $post_types = array_diff(get_post_types(array('public' => true)), array('attachment')); $post_type_in = "'" . implode("','", $post_types) . "'"; if ($post_ids = scoper_get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type IN ({$post_type_in}) ORDER BY post_type, post_title")) { $stored_attachments = array(); if ($results = scoper_get_results("SELECT post_parent, guid FROM {$wpdb->posts} WHERE post_type = 'attachment'")) { foreach ($results as $row) { if (!isset($stored_attachments[$row->post_parent])) { $stored_attachments[$row->post_parent] = array(); } $stored_attachments[$row->post_parent][$row->guid] = true; } } // for reasonable memory usage, only hold 10 posts in memory at a time $found_links = 0; $num_inserted = 0; $num_posts = count($post_ids); $bite_size = 10; $num_bites = $num_posts / $bite_size; if ($num_posts % $bite_size) { $num_bites++; } $upload_path = $uploads['baseurl']; $upload_dir = $uploads['basedir']; if ($echo) { printf(__("<strong>checking %s posts / pages...</strong>", 'scoper'), $num_posts); echo '<br /><br />'; } for ($i = 0; $i < $num_bites; $i++) { $id_in = "'" . implode("','", array_slice($post_ids, $i * $bite_size, $bite_size)) . "'"; if (!($results = scoper_get_results("SELECT ID, post_content, post_author, post_title, post_type FROM {$wpdb->posts} WHERE ID IN ({$id_in})"))) { continue; } foreach ($results as $row) { $linked_uploads = array(); // preg_match technique learned from http://stackoverflow.com/questions/138313/how-to-extract-img-src-title-and-alt-from-html-using-php $tags = array('img' => array(), 'a' => array()); $content = $row->post_content; preg_match_all('/<img[^>]+>/i', $row->post_content, $tags['img']); preg_match_all('/<a[^>]+>/i', $row->post_content, $tags['a']); // don't care that this will terminate with any enclosed tags (i.e. img) foreach (array_keys($tags) as $tag_type) { foreach ($tags[$tag_type]['0'] as $found_tag) { $found_attribs = array('src' => '', 'href' => '', 'title' => '', 'alt' => ''); if (!preg_match_all('/(alt|title|src|href)=("[^"]*")/i', $found_tag, $tag_attributes)) { continue; } foreach ($tag_attributes[1] as $key => $attrib_name) { $found_attribs[$attrib_name] = trim($tag_attributes[2][$key], "'" . '"'); } if (!$found_attribs['href'] && !$found_attribs['src']) { continue; } $file_url = $found_attribs['src'] ? $found_attribs['src'] : $found_attribs['href']; if (!strpos($file_url, '.')) { continue; } if (MULTISITE && strpos($uploads['url'], 'blogs.dir')) { $file_url = str_replace('/files/', "/wp-content/blogs.dir/{$blog_id}/files/", $file_url); } // links can't be registered as attachments unless they're in the WP uploads path if (false === strpos($file_url, $upload_path)) { if ($echo) { //printf( _ x( '<span class="rs-brown">skipping unfilterable file in %1$s "%2$s":</span> %3$s', 'post_type, post_title, file_url', 'scoper' ), __(ucwords($row->post_type)), $row->post_title, $file_url); printf(__('<span class="rs-brown">skipping unfilterable file in %1$s "%2$s":</span> %3$s', 'scoper'), __(ucwords($row->post_type)), $row->post_title, $file_url); echo '<br /><br />'; } continue; } // make sure the linked file actually exists if (!file_exists(str_replace($upload_path, $upload_dir, $file_url))) { if ($echo) { //printf( _ x( '<span class="rs-brown">skipping unfilterable file in %1$s "%2$s":</span> %3$s', 'post_type, post_title, file_url', 'scoper' ), __(ucwords($row->post_type)), $row->post_title, $file_url); printf(__('<span class="rs-red">skipping missing file in %1$s "%2$s":</span> %3$s', 'scoper'), __(ucwords($row->post_type)), $row->post_title, $file_url); echo '<br /><br />'; } continue; } $caption = $found_attribs['title'] ? $found_attribs['title'] : $found_attribs['alt']; // we might find the same file sourced in both link and img tags if (!isset($linked_uploads[$file_url]) || !$linked_uploads[$file_url]) { $found_links++; $linked_uploads[$file_url] = $caption; } } // end foreach found tag } // end foreach loop on 'img' and 'a' foreach ($linked_uploads as $file_url => $caption) { $unsuffixed_file_url = preg_replace("/-[0-9]{2,4}x[0-9]{2,4}./", '.', $file_url); $file_info = wp_check_filetype($unsuffixed_file_url); if (!isset($stored_attachments[$row->ID][$unsuffixed_file_url])) { $att = array(); $att['guid'] = $unsuffixed_file_url; $info = pathinfo($unsuffixed_file_url); if (isset($info['filename'])) { $att['post_name'] = $info['filename']; $att['post_title'] = $info['filename']; } $att['post_excerpt'] = $caption; $att['post_author'] = $row->post_author; $att['post_parent'] = $row->ID; $att['post_category'] = wp_get_post_categories($row->ID); if (isset($file_info['type'])) { $att['post_mime_type'] = $file_info['type']; } $num_inserted++; if ($echo) { printf(__('<span class="rs-green"><strong>new attachment</strong> in %1$s "%2$s":</span> %3$s', 'scoper'), __(ucwords($row->post_type)), $row->post_title, $file_url); } //printf(_ x( '<span class="rs-green"><strong>new attachment</strong> in %1$s "%2$s":</span> %3$s', 'post_type, post_title, file_url', 'scoper' ), __(ucwords($row->post_type)), $row->post_title, $file_url); wp_insert_attachment($att); } else { if ($echo) { printf(__('<span class="rs-blue">attachment OK in %1$s "%2$s":</span> %3$s', 'scoper'), __(ucwords($row->post_type)), $row->post_title, $file_url); } //printf(_ x( '<span class="rs-blue">attachment OK in %1$s "%2$s":</span> %3$s', 'post_type, post_title, file_url', 'scoper' ), __(ucwords($row->post_type)), $row->post_title, $file_url); } if ($echo) { echo '<br /><br />'; } } // end foreach linked_uploads } // end foreach post in this bite } // endif for each 10-post bite if ($echo) { echo '<strong>'; printf(__("Operation complete: %s linked uploads were found in your post / page content.", 'scoper'), $found_links); echo '<br /><br />'; if ($num_inserted) { printf(__('<strong>%s attachment records were added to the database.</strong>', 'scoper'), $num_inserted); echo '<br /><br />'; } elseif ($found_links) { _e('All linked uploads are already registered as attachments.', 'scoper'); echo '<br /><br />'; } } } if (count($blog_ids) > 1) { echo '<hr />'; } } // end foreach site if (count($blog_ids) > 1) { switch_to_blog($orig_blog_id); } return true; }
function clear_restrictions($scope, $src_or_tx_name, $obj_or_term_id, $args = array()) { $defaults = array('inherited_only' => false, 'clear_propagated' => false); $args = array_merge($defaults, (array) $args); extract($args); global $wpdb; $inherited_clause = $inherited_only ? "AND inherited_from > 0" : ''; $qry = "SELECT requirement_id FROM {$wpdb->role_scope_rs} WHERE topic = '{$scope}' AND src_or_tx_name = '{$src_or_tx_name}' {$inherited_clause} AND obj_or_term_id = '{$obj_or_term_id}'"; $req_ids = scoper_get_col($qry); if ($req_ids) { $qry = "DELETE FROM {$wpdb->role_scope_rs} WHERE requirement_id IN ('" . implode("', '", $req_ids) . "')"; if ($clear_propagated) { $qry .= " OR inherited_from IN ('" . implode("', '", $req_ids) . "') "; } scoper_query($qry); } }
function awp_query_descendant_ids($table_name, $col_id, $col_parent, $parent_id) { global $wpdb; $descendant_ids = array(); // todo: abstract this $type_clause = $table_name == $wpdb->posts ? "AND post_type != 'revision'" : ''; $query = "SELECT {$col_id} FROM {$table_name} WHERE {$col_parent} = '{$parent_id}' {$type_clause}"; if ($results = scoper_get_col($query)) { foreach ($results as $id) { if (!in_array($id, $descendant_ids)) { $descendant_ids[] = $id; $next_generation = awp_query_descendant_ids($table_name, $col_id, $col_parent, $id, $descendant_ids); $descendant_ids = array_merge($descendant_ids, $next_generation); } } } return $descendant_ids; }
function display_ui_group_roles($group_id) { $users = ScoperAdminLib::get_group_members($group_id, COL_ID_RS); $args = array('disable_user_roles' => true, 'filter_usergroups' => array($group_id => true), 'disable_wp_roles' => true); $user_id = $users ? $users[0] : 0; $user = new WP_Scoped_User($user_id, '', $args); if (!$users) { $user->groups = array($group_id => true); } if ($group = ScoperAdminLib::get_group($group_id)) { if (!strpos($group->meta_id, '_nr_')) { global $wpdb; echo '<div class="rs-group-profile">'; if (IS_MU_RS && scoper_get_option('mu_sitewide_groups')) { global $blog_id; $blog_ids = scoper_get_col("SELECT blog_id FROM {$wpdb->blogs} ORDER BY blog_id"); $orig_blog_id = $blog_id; } else { $blog_ids = array('1'); } foreach ($blog_ids as $id) { if (count($blog_ids) > 1) { switch_to_blog($id); } if (!$wpdb->get_results("SHOW TABLES LIKE '{$wpdb->user2role2object_rs}'")) { continue; } ScoperProfileUI::display_ui_user_roles($user, true); //arg: groups only } echo '</div>'; if (count($blog_ids) > 1) { switch_to_blog($orig_blog_id); } } } }
function scoper_object_roles_list($viewing_user, $args = array()) { $html = ''; if (!USER_ROLES_RS && !GROUP_ROLES_RS) { wp_die(__awp('Cheatin’ uh?')); } $defaults = array('enforce_duration_limits' => true, 'is_user_profile' => false, 'echo' => true); $args = array_merge($defaults, (array) $args); extract($args); global $scoper, $wpdb, $current_user; if ($viewing_user) { if (!is_object($viewing_user)) { global $current_rs_user; if ($viewing_user == $current_rs_user->ID) { $viewing_user = $current_rs_user; } else { $viewing_user = new WP_Scoped_User($viewing_user); } } } $all_roles = array(); $role_display = array(); foreach ($scoper->role_defs->get_all_keys() as $role_handle) { if ($viewing_user) { $role_display[$role_handle] = $scoper->role_defs->get_display_name($role_handle, OBJECT_UI_RS); } else { $role_display[$role_handle] = $scoper->role_defs->get_abbrev($role_handle, OBJECT_UI_RS); } } if (!$is_user_profile) { $require_blogwide_editor = scoper_get_option('role_admin_blogwide_editor_only'); if ('admin' === $require_blogwide_editor && !is_user_administrator_rs()) { return false; } if ('admin_content' === $require_blogwide_editor && !is_content_administrator_rs()) { return false; } } else { $require_blogwide_editor = false; } foreach ($scoper->data_sources->get_all() as $src_name => $src) { $otype_count = 0; if (!empty($src->taxonomy_only) || $src_name == 'group' && !$viewing_user) { continue; } $strict_objects = $scoper->get_restrictions(OBJECT_SCOPE_RS, $src_name); foreach ($src->object_types as $object_type => $otype) { $otype_count++; $disable_role_admin = false; if ($require_blogwide_editor) { if (!$scoper->user_can_edit_blogwide('post', $object_type, array('require_others_cap' => true))) { $disable_role_admin = true; } } if (!empty($src->cols->type) && !empty($otype->name)) { $col_type = $src->cols->type; $otype_clause = "AND {$src->table}.{$col_type} = '{$otype->name}'"; } elseif ($otype_count < 2) { $otype_clause = ''; } else { continue; } $col_id = $src->cols->id; $col_name = $src->cols->name; $ug_clause_for_user_being_viewed = $viewing_user ? $viewing_user->get_user_clause('uro') : ''; // TODO: replace join with uro subselect $qry = "SELECT DISTINCT {$src->table}.{$col_name}, {$src->table}.{$col_id}, uro.role_name, uro.date_limited, uro.start_date_gmt, uro.end_date_gmt" . " FROM {$src->table} "; $join = " INNER JOIN {$wpdb->user2role2object_rs} AS uro" . " ON uro.obj_or_term_id = {$src->table}.{$col_id}" . " AND uro.src_or_tx_name = '{$src_name}'" . " AND uro.scope = 'object' AND uro.role_type = 'rs'"; $duration_clause = $enforce_duration_limits ? scoper_get_duration_clause("{$src->table}.{$src->cols->date}") : ''; $status_clause = 'post' == $src_name ? "AND post_status != 'auto-draft'" : ''; // TODO: version update script to delete post roles on auto-drafts (stored via default roles) $where = " WHERE 1=1 {$status_clause} {$otype_clause} {$duration_clause} {$ug_clause_for_user_being_viewed}"; $orderby = " ORDER BY {$src->table}.{$col_name} ASC, uro.role_name ASC"; $qry .= $join . $where . $orderby; $results = scoper_get_results($qry); if (!is_user_administrator_rs()) { // no need to filter admins - just query the assignments // only list role assignments which the logged-in user can administer $args['required_operation'] = OP_EDIT_RS; // Possible TODO: re-implement OP_ADMIN distinction with admin-specific capabilities /* if ( cr_get_reqd_caps( $src_name, OP_ADMIN_RS, $object_type ) { $args['required_operation'] = OP_ADMIN_RS; } else { $reqd_caps = array(); foreach (array_keys($src->statuses) as $status_name) { $admin_caps = $scoper->cap_defs->get_matching($src_name, $object_type, OP_ADMIN_RS, $status_name); $delete_caps = $scoper->cap_defs->get_matching($src_name, $object_type, OP_DELETE_RS, $status_name); $reqd_caps[$object_type][$status_name] = array_merge(array_keys($admin_caps), array_keys($delete_caps)); } $args['force_reqd_caps'] = $reqd_caps; } */ $qry = "SELECT {$src->table}.{$col_id} FROM {$src->table} WHERE 1=1"; $args['require_full_object_role'] = true; $qry_flt = apply_filters('objects_request_rs', $qry, $src_name, $object_type, $args); $cu_admin_results = scoper_get_col($qry_flt); if (empty($viewing_user) || $current_user->ID != $viewing_user->ID) { foreach ($results as $key => $row) { if (!in_array($row->{$col_id}, $cu_admin_results)) { unset($results[$key]); } } } else { // for current user's view of their own user profile, just de-link unadminable objects $link_roles = array(); $link_objects = array(); if (!$disable_role_admin) { foreach ($results as $key => $row) { if (in_array($row->{$col_id}, $cu_admin_results)) { $link_roles[$row->{$col_id}] = true; } } $args['required_operation'] = OP_EDIT_RS; $args['require_full_object_role'] = false; if (isset($args['force_reqd_caps'])) { unset($args['force_reqd_caps']); } $qry_flt = apply_filters('objects_request_rs', $qry, $src_name, $object_type, $args); $cu_edit_results = scoper_get_col($qry_flt); foreach ($results as $key => $row) { if (in_array($row->{$col_id}, $cu_edit_results)) { $link_objects[$row->{$col_id}] = true; } } } } } $object_roles = array(); $objnames = array(); if ($results) { $got_object_roles = true; foreach ($results as $row) { if (!isset($objnames[$row->{$col_id}])) { if ('post' == $src->name) { $objnames[$row->{$col_id}] = apply_filters('the_title', $row->{$col_name}, $row->{$col_id}); } else { $objnames[$row->{$col_id}] = $row->{$col_name}; } } $role_handle = 'rs_' . $row->role_name; if ($row->date_limited) { $duration_key = serialize(array('start_date_gmt' => $row->start_date_gmt, 'end_date_gmt' => $row->end_date_gmt)); } else { $duration_key = ''; } $object_roles[$duration_key][$row->{$col_id}][$role_handle] = true; } } else { continue; } ?> <?php $title_roles = __('edit roles', 'scoper'); foreach (array_keys($object_roles) as $duration_key) { $date_caption = ''; $limit_class = ''; $limit_style = ''; $link_class = ''; if ($duration_key) { $html .= "<h3 style='margin-bottom:0'>{$date_caption}</h3>"; $duration_limits = unserialize($duration_key); $duration_limits['date_limited'] = true; ScoperAdminUI::set_agent_formatting($duration_limits, $date_caption, $limit_class, $link_class, $limit_style); $title = "title='{$date_caption}'"; $date_caption = '<span class="rs-gray"> ' . trim($date_caption) . '</span>'; } else { $title = "title='{$title_roles}'"; } if (!$disable_role_admin && (is_user_administrator_rs() || $cu_admin_results)) { //if ( ( $src_name != $object_type ) && ( 'post' != $object_type ) ) { // menu links currently assume unique object type names // $roles_page = "rs-roles-{$object_type}_{$src_name}"; //} else { $roles_page = "rs-{$object_type}-roles"; //} $url = "admin.php?page={$roles_page}"; $html .= "<h4><a name='{$object_type}' href='{$url}'><strong>" . sprintf(__('%1$s Roles%2$s:', 'scoper'), $otype->labels->singular_name, '</strong></a><span style="font-weight:normal">' . $date_caption) . "</span></h4>"; } else { $html .= "<h4><strong>" . sprintf(__('%1$s Roles%2$s:', 'scoper'), $otype->labels->singular_name, $date_caption) . "</strong></h4>"; } $html .= "<ul class='rs-termlist'><li>" . "<table class='widefat'>" . "<thead>" . "<tr class='thead'>" . "\t<th class='rs-tightcol'>" . __('ID') . "</th>" . "\t<th>" . __awp('Name') . "</th>" . "\t<th>" . __('Role Assignments', 'scoper') . "</th>" . "</tr>" . "</thead>"; $id_clause = isset($role_codes[$role_handle]) ? "id='roles-{$role_codes[$role_handle]}'" : ''; $html .= "<tbody {$id_clause}>"; $style = ' class="rs-backwhite"'; $title_item = sprintf(__('edit %s', 'scoper'), agp_strtolower($otype->labels->singular_name)); foreach ($object_roles[$duration_key] as $obj_id => $roles) { $object_name = esc_attr($objnames[$obj_id]); $html .= "\n\t<tr{$style}>"; $link_this_object = !isset($link_objects) || isset($link_objects[$obj_id]); // link from object ID to the object type's default editor, if defined if ($link_this_object && !empty($src->edit_url)) { $src_edit_url = sprintf($src->edit_url, $obj_id); $html .= "<td><a href='{$src_edit_url}' class='edit' title='{$title_item}'>{$obj_id}</a></td>"; } else { $html .= "<td>{$obj_id}</td>"; } $name = !empty($objnames[$obj_id]) ? $objnames[$obj_id] : __('(untitled)', 'scoper'); // link from object name to our "Edit Object Role Assignment" interface $link_this_role = !isset($link_roles) || isset($link_roles[$obj_id]); if ($link_this_role) { if ('group' == $object_type) { $rs_edit_url = sprintf($src->edit_url, $obj_id); } else { $rs_edit_url = "admin.php?page=rs-object_role_edit&src_name={$src_name}&object_type={$object_type}&object_id={$obj_id}&object_name={$object_name}"; } $html .= "\n\t<td><a {$title}{$limit_style}class='{$link_class}{$limit_class}' href='{$rs_edit_url}'>{$name}</a></td>"; } else { $html .= "\n\t<td>{$name}</td>"; } $html .= "<td>"; $role_list = array(); foreach (array_keys($roles) as $role_handle) { // roles which require object assignment are asterisked (bolding would contradict the notation of term roles list, where propogating roles are bolded) if (isset($strict_objects['restrictions'][$role_handle][$obj_id]) || isset($strict_objects['unrestrictions'][$role_handle]) && is_array($strict_objects['unrestrictions'][$role_handle]) && !isset($strict_objects['unrestrictions'][$role_handle][$obj_id])) { $role_list[] = "<span class='rs-backylw'>" . $role_display[$role_handle] . '</span>'; } else { $role_list[] = $role_display[$role_handle]; } } $html .= implode(', ', $role_list); $html .= '</td></tr>'; $style = ' class="alternate"' == $style ? ' class="rs-backwhite"' : ' class="alternate"'; } // end foreach object_roles $html .= '</tbody></table>'; $html .= '</li></ul><br />'; } // end foreach role date range } // end foreach object_types } // end foreach data source if ($echo) { echo $html; } else { return $html; } }
function scoper_flt_page_parent($parent_id) { if ('no_parent_filter' == scoper_get_option('lock_top_pages')) { return (int) $parent_id; } if (!empty($_REQUEST['post_ID'])) { $post_id = $_REQUEST['post_ID']; } elseif (!empty($_REQUEST['post_id'])) { $post_id = $_REQUEST['post_id']; } else { return (int) $parent_id; } if (!empty($post_id)) { if ($parent_id == $post_id) { // normal revision save return (int) $parent_id; } } if (defined('RVY_VERSION')) { global $revisionary; if (!empty($revisionary->admin->revision_save_in_progress)) { return (int) $parent_id; } } if (empty($_POST['post_type'])) { return (int) $parent_id; } // Make sure the selected parent is valid. Merely an anti-hacking precaution to deal with manually fudged POST data global $scoper, $wpdb; $post_type = sanitize_key($_POST['post_type']); $plural_name = plural_name_from_cap_rs(get_post_type_object($post_type)); $args = array(); $args['alternate_reqd_caps'][0] = array("create_child_{$plural_name}"); if ($descendant_ids = scoper_get_page_descendant_ids($post_id)) { $exclusion_clause = "AND ID NOT IN('" . implode("','", $descendant_ids) . "')"; } else { $exclusion_clause = ''; } $qry_parents = "SELECT ID FROM {$wpdb->posts} WHERE post_type = '{$post_type}' AND post_status != 'auto-draft' {$exclusion_clause}"; $qry_parents = apply_filters('objects_request_rs', $qry_parents, 'post', $post_type, $args); $valid_parents = scoper_get_col($qry_parents); $post = get_post($post_id); if ($parent_id) { if ($post && !in_array($parent_id, $valid_parents)) { $parent_id = $post->post_parent; } } else { if (!$GLOBALS['scoper_admin_filters']->user_can_associate_main($post_type)) { $already_published = false; if ($post) { if ($saved_status_object = get_post_status_object($post->post_status)) { $already_published = $saved_status_object->public || $saved_status_object->private; } } if ($already_published) { // If post was previously published to another parent, revert it $parent_id = $post->post_parent; } elseif ($valid_parents) { // otherwise default to a valid parent sort($valid_parents); $parent_id = reset($valid_parents); $_POST['parent_id'] = (int) $parent_id; // for subsequent post_status filter } } } return (int) $parent_id; }
function identify_protected_posts($attachment_id = 0, $attachments = false, $cols = '', $args = array()) { $defaults = array('use_object_restrictions' => true, 'use_term_restrictions' => true, 'use_private_status' => true, 'guid' => ''); $args = array_merge($defaults, (array) $args); extract($args); global $wpdb, $scoper; if (!isset($scoper) || is_null($scoper)) { scoper_get_init_options(); scoper_init(); } if (empty($scoper->taxonomies)) { $scoper->load_config(); } $restricted_roles = array(); $unrestricted_roles = array(); // TODO: also protect uploads based on restriction of other taxonomies $restricted_terms = array(); $restricted_objects = array(); $term_restriction_clause = ''; $object_restriction_clause = ''; $limit_clause = ''; $unattached_clause = ''; global $scoper; $reader_roles = array(); foreach ($scoper->role_defs->role_caps as $role_handle => $role_caps) { $caps_by_op = $scoper->cap_defs->organize_caps_by_op(array_keys($role_caps)); if (count($caps_by_op) == 1 && 'read' == key($caps_by_op)) { $reader_roles[] = $role_handle; } } $role_clause = "AND rs.role_name IN ('" . implode("','", scoper_role_handles_to_names($reader_roles)) . "')"; //if ( $use_private_status ) // $role_clause = ( 'rs' == SCOPER_ROLE_TYPE ) ? "AND rs.role_name IN ('post_reader', 'page_reader')" : ''; // if also checking for private status, don't need to check for restriction of private_reader roles //else // $role_clause = ( 'rs' == SCOPER_ROLE_TYPE ) ? "AND rs.role_name IN ('post_reader', 'page_reader', 'private_post_reader', 'private_page_reader')" : ''; if ($use_term_restrictions) { $term_restriction_query = "SELECT rs.obj_or_term_id AS term_id, rs.role_name, rs.max_scope FROM {$wpdb->role_scope_rs} AS rs " . "INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.taxonomy = rs.src_or_tx_name AND tt.taxonomy = 'category' AND tt.term_taxonomy_id = rs.obj_or_term_id " . "WHERE rs.role_type = 'rs' AND rs.require_for IN ('entity', 'both') AND rs.topic = 'term' {$role_clause}"; $term_default_restriction_query = "SELECT rs.role_name FROM {$wpdb->role_scope_rs} AS rs " . "WHERE rs.role_type = 'rs' AND rs.require_for IN ('children', 'both') AND rs.topic = 'term' AND rs.max_scope = 'term' AND rs.src_or_tx_name = 'category' AND rs.obj_or_term_id = '0' {$role_clause}"; $all_terms = array(); $all_terms['category'] = $scoper->get_terms('category', false, COL_ID_RS); if ($results = scoper_get_results($term_restriction_query)) { foreach ($results as $row) { if ('blog' == $row->max_scope) { $unrestricted_roles['category'][$row->role_name][] = $row->term_id; } else { $restricted_roles['category'][$row->role_name][] = $row->term_id; } } } // if there a role is default-restricted, mark all terms as restricted (may be unrestricted later) if ($results = scoper_get_col($term_default_restriction_query)) { foreach ($results as $role_name) { if (isset($unrestricted_roles['category'][$role_name])) { $default_restricted = array_diff($all_terms['category'], $unrestricted_roles['category'][$role_name]); } else { $default_restricted = $all_terms['category']; } if (isset($restricted_roles['category'][$role_name])) { $restricted_roles['category'][$role_name] = array_unique(array_merge($restricted_roles['category'][$role_name], $default_restricted)); } else { $restricted_roles['category'][$role_name] = $default_restricted; } } } $restricted_terms['category'] = isset($restricted_roles['category']) ? agp_array_flatten($restricted_roles['category']) : array(); if ($restricted_terms['category']) { $term_restriction_clause = "OR post_parent IN ( SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} " . "INNER JOIN {$wpdb->term_relationships} AS tr ON tr.object_id = {$wpdb->posts}.ID " . "WHERE tr.term_taxonomy_id IN ('" . implode("','", $restricted_terms['category']) . "') )"; } } if ($attachment_id) { if (is_array($attachment_id)) { $id_clause = "AND ID IN ('" . implode("','", $attachment_id) . "')"; } else { $id_clause = "AND ID = '{$attachment_id}'"; $limit_clause = 'LIMIT 1'; } } elseif ($guid) { $id_clause = "AND guid = '{$file_path}'"; } else { $id_clause = ''; } if (defined('SCOPER_NO_THUMBNAIL_FILTER')) { if ($thumbnail_ids = scoper_get_col("SELECT DISTINCT meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_thumbnail_id'")) { $id_clause .= " AND ID NOT IN ('" . implode("','", $thumbnail_ids) . "')"; } } if ($attachments) { // to reduce pool of objects, we only care about those that have an attachment $attachment_query = "SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} WHERE {$wpdb->posts}.ID IN ( SELECT post_parent FROM {$wpdb->posts} WHERE post_type = 'attachment' {$id_clause} ) "; } if ($use_object_restrictions) { $object_restriction_query = "SELECT rs.obj_or_term_id AS obj_id, rs.role_name, rs.max_scope FROM {$wpdb->role_scope_rs} AS rs " . "WHERE rs.role_type = 'rs' AND rs.require_for IN ('entity', 'both') AND rs.topic = 'object' AND rs.src_or_tx_name = 'post' {$role_clause} AND rs.obj_or_term_id IN ( {$attachment_query} )"; $object_default_restriction_query = "SELECT rs.role_name FROM {$wpdb->role_scope_rs} AS rs " . "WHERE rs.require_for IN ('children', 'both') AND rs.topic = 'object' AND rs.max_scope = 'object' AND rs.src_or_tx_name = 'post' AND rs.obj_or_term_id = '0' {$role_clause}"; $all_objects = array(); $all_objects['post'] = scoper_get_col($attachment_query); $restricted_roles = array(); $unrestricted_roles = array(); if ($results = scoper_get_results($object_restriction_query)) { foreach ($results as $row) { if ('blog' == $row->max_scope) { $unrestricted_roles['post'][$row->role_name][] = $row->obj_id; } else { $restricted_roles['post'][$row->role_name][] = $row->obj_id; } } } // if there a role is default-restricted, mark all terms as restricted (may be unrestricted later) if ($results = scoper_get_col($object_default_restriction_query)) { foreach ($results as $role_name) { if (isset($unrestricted_roles['category'][$role_name])) { $default_restricted = array_diff($all_terms['post'], $unrestricted_roles['post'][$role_name]); } else { $default_restricted = $all_objects['post']; } if (isset($restricted_roles['post'][$role_name])) { $restricted_roles['post'][$role_name] = array_unique(array_merge($restricted_roles['post'][$role_name], $default_restricted)); } else { $restricted_roles['post'][$role_name] = $default_restricted; } } } if (!empty($restricted_roles)) { $restricted_objects['post'] = array_unique(agp_array_flatten($restricted_roles['post'])); if ($restricted_objects['post']) { $object_restriction_clause = "OR post_parent IN ( SELECT ID FROM {$wpdb->posts} WHERE ID IN ('" . implode("','", $restricted_objects['post']) . "') )"; } } } if ($use_private_status) { $status_query = "AND post_parent IN ( SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} WHERE {$wpdb->posts}.post_status = 'private' )"; } if ($attachments) { $attachment_type_clause = "post_type = 'attachment' AND"; $unattached_clause = defined('SCOPER_BLOCK_UNATTACHED_UPLOADS') ? " OR post_parent < 1" : ''; } $single_col = false; if (COLS_ALL_RS === $cols) { $query_cols = '*'; } elseif (COL_ID_RS == $cols) { $query_cols = 'ID'; $single_col = true; } elseif (COLS_ID_DISPLAYNAME_RS == $cols) { if ($attachment) { $query_cols = 'ID, post_title, guid'; } else { $query_cols = 'ID, post_title'; } } else { if ($attachments) { $query_cols = 'ID, guid'; } else { $query_cols = 'ID'; $single_col = true; } } $query = "SELECT {$query_cols} FROM {$wpdb->posts} WHERE {$attachment_type_clause} ( 1=1 {$status_query} {$term_restriction_clause} {$object_restriction_clause} {$unattached_clause} ) {$id_clause} ORDER BY ID DESC {$limit_clause}"; if ($attachment_id && !is_array($attachment_id)) { if ($single_col) { $results = scoper_get_var($query); } else { $results = scoper_get_row($query); } } else { if ($single_col) { $results = scoper_get_col($query); } else { $results = scoper_get_results($query); } } return $results; }
function get_groups_for_user($user_id, $args = array()) { if (empty($args['status'])) { $status = 'active'; } elseif ('any' == $args['status']) { $args['no_cache'] = true; $status = ''; } else { $args['no_cache'] = true; $status = $args['status']; } if (empty($args['no_cache'])) { $cache = wpp_cache_get($user_id, 'group_membership_for_user'); if (is_array($cache)) { return $cache; } } global $wpdb; if (!$wpdb->user2group_rs) { return array(); } if (!$user_id) { // include WP metagroup for anonymous user return array_fill_keys(scoper_get_col("SELECT {$wpdb->groups_id_col} FROM {$wpdb->groups_rs} WHERE {$wpdb->groups_rs}.{$wpdb->groups_meta_id_col} = 'wp_anon'"), 'true'); } $status_clause = $status ? "AND status = '{$status}'" : ''; $query = "SELECT {$wpdb->user2group_gid_col} FROM {$wpdb->user2group_rs} WHERE {$wpdb->user2group_uid_col} = '{$user_id}' {$status_clause} ORDER BY {$wpdb->user2group_gid_col}"; if (!($user_groups = scoper_get_col($query))) { $user_groups = array(); } // include WP metagroup(s) for WP blogrole(s) $metagroup_ids = array(); if (!empty($args['metagroup_roles'])) { foreach (array_keys($args['metagroup_roles']) as $role_handle) { $metagroup_ids[] = 'wp_role_' . str_replace('wp_', '', $role_handle); } } if ($metagroup_ids) { $meta_id_in = "'" . implode("', '", $metagroup_ids) . "'"; $query = "SELECT {$wpdb->groups_id_col} FROM {$wpdb->groups_rs}" . " WHERE {$wpdb->groups_rs}.{$wpdb->groups_meta_id_col} IN ({$meta_id_in})" . " ORDER BY {$wpdb->groups_id_col}"; if ($meta_groups = scoper_get_col($query)) { $user_groups = array_merge($user_groups, $meta_groups); } } if ($user_groups && empty($args['no_cache'])) { // users should always be in at least a metagroup. Problem with caching empty result on user creation beginning with WP 2.8 $user_groups = array_fill_keys($user_groups, 1); wpp_cache_set($user_id, $user_groups, 'group_membership_for_user'); } return $user_groups; }