function flt_get_editable_authors($unfiltered_results) { global $wpdb, $scoper, $post; if (!($post_type = cr_find_post_type())) { return $unfiltered_results; } if (!($post_type_obj = get_post_type_object($post_type))) { return $unfiltered_results; } $have_cap = cr_user_can($post_type_obj->cap->edit_others_posts, $post->ID, 0, array('require_full_object_role' => true)); if ($have_cap) { return $scoper->users_who_can($post_type_obj->cap->edit_posts, COLS_ALL_RS); } else { if ($post->ID) { if ($current_author = $scoper->data_sources->get_from_db('owner', 'post', $post->ID)) { $force_user_id = $current_author; } } else { global $current_user; $force_user_id = $current_user->ID; } if ($force_user_id) { $display_name = $wpdb->get_var("SELECT display_name FROM {$wpdb->users} WHERE ID = '{$force_user_id}'"); $users = array((object) array('ID' => $force_user_id, 'display_name' => $display_name)); return $users; } } //log_mem_usage_rs( 'flt_get_editable_authors()' ); return $unfiltered_results; }
function get_reqd_caps() { $reqd_caps = array(); $generic_uri = in_array($GLOBALS['pagenow'], array('index.php', 'comments.php')); if (!$generic_uri && ($_post_type = cr_find_post_type('', false))) { // arg: don't return 'post' as default if detection fails $post_types = array($_post_type => get_post_type_object($_post_type)); } else { $post_types = array_diff_key(get_post_types(array('public' => true), 'object'), array('attachment' => true)); } $use_post_types = scoper_get_option('use_post_types'); $post_statuses = get_post_stati(array('internal' => null), 'object'); foreach ($post_types as $_post_type => $type_obj) { if (empty($use_post_types[$_post_type])) { continue; } foreach ($post_statuses as $status => $status_obj) { $reqd_caps[$_post_type][$status] = array($type_obj->cap->edit_others_posts); if (scoper_get_option('require_moderate_comments_cap')) { $reqd_caps[$_post_type][$status][] = 'moderate_comments'; } if ($status_obj->private) { $reqd_caps[$_post_type][$status][] = $type_obj->cap->edit_private_posts; } if ($status_obj->public || 'future' == $status) { $reqd_caps[$_post_type][$status][] = $type_obj->cap->edit_published_posts; } } } return $reqd_caps; }
function flt_defeat_publish_filter($where) { $post_type = cr_find_post_type(); $post_type_obj = get_post_type_object($post_type); $object_id = scoper_get_object_id('post', $post_type); // don't alter the query if RS query filtering is disabled, or if this maneuver has been disabled via constant // note: for non-administrators, QueryInterceptor_RS::flt_objects_where will convert the publish requirement to publish OR private, if the user's blog role or RS-assigned roles grant private access if (!is_content_administrator_rs() || defined('SCOPER_RETAIN_PUBLISH_FILTER') || defined('DISABLE_QUERYFILTERS_RS')) { return $where; } global $wp_query; if (is_admin() && !empty($wp_query->query['post_status'])) { // if a specific status was requested by URI, don't force inclusion of others return $where; } // don't alter the where clause if in wp-admin and not filtering by taxonomy if (is_admin()) { global $wp_query; if (empty($wp_query) && empty($wp_query->is_tax)) { return $where; } } global $wpdb, $current_user; // don't alter the where clause for anonymous users if (empty($current_user->ID)) { return $where; } $where = preg_replace("/{$wpdb->posts}.post_status\\s*=\\s*'publish'/", "({$wpdb->posts}.post_status = 'publish' OR {$wpdb->posts}.post_status = 'private')", $where); $where = preg_replace("/p2.post_status\\s*=\\s*'publish'/", "(p2.post_status = 'publish' OR p2.post_status = 'private')", $where); $where = preg_replace("/p.post_status\\s*=\\s*'publish'/", "(p.post_status = 'publish' OR p.post_status = 'private')", $where); return $where; }
function flt_adjacent_post_where($where) { global $wpdb, $query_interceptor, $current_user; if (!empty($current_user->ID)) { $where = str_replace(" AND p.post_status = 'publish'", '', $where); } // get_adjacent_post() function includes 'WHERE ' at beginning of $where $where = str_replace('WHERE ', 'AND ', $where); $post_type = cr_find_post_type(); $args = array('source_alias' => 'p', 'skip_teaser' => true); // skip_teaser arg ensures unreadable posts will not be linked $where = 'WHERE 1=1 ' . $query_interceptor->flt_objects_where($where, 'post', $post_type, $args); return $where; }
function flt_manage_posts_columns($defaults) { global $current_user, $scoper, $scoper_role_usage; $object_type = cr_find_post_type(); if ($blogwide_role_requirement = scoper_get_option('role_admin_blogwide_editor_only')) { if ('admin' == $blogwide_role_requirement && !is_user_administrator_rs()) { return $defaults; } elseif ('content_admin' == $blogwide_role_requirement && !is_content_administrator_rs()) { return $defaults; } elseif ($blogwide_role_requirement) { if (!$scoper->user_can_edit_blogwide('post', $object_type, array('require_others_cap' => true))) { return $defaults; } } } $use_object_roles = scoper_get_otype_option('use_object_roles', 'post', $object_type); $use_term_roles = scoper_get_otype_option('use_term_roles', 'post', $object_type); if ($use_term_roles && !empty($scoper_role_usage->any_restricted_terms) || $use_object_roles && !empty($scoper_role_usage->any_restricted_objects)) { if (scoper_get_otype_option('restrictions_column', 'post', $object_type)) { $defaults['restricted'] = __('Restrict', 'scoper'); } } if (!empty($scoper_role_usage->have_termrole_ids['post'])) { if (scoper_get_otype_option('term_roles_column', 'post', $object_type)) { $defaults['termroles'] = __('Term Roles', 'scoper'); } } if ($use_object_roles && !empty($scoper_role_usage->have_objrole_ids['post'])) { if (scoper_get_otype_option('object_roles_column', 'post', $object_type)) { $otype_display_name = $scoper->data_sources->member_property('post', 'object_types', $object_type, 'display_name'); //$defaults['objroles'] = sprintf( _ x('%s Roles', 'Post or Page', 'scoper'), $otype_display_name); $defaults['objroles'] = sprintf(__('%s Roles', 'scoper'), $otype_display_name); } } return $defaults; }
function draw_object_roles_content($object, $box) { if (empty($box['id'])) { return; } // id format: src_name:object_type:role_handle (As of WP 2.7, this is only safe way to transfer these parameters) //$role_attribs = explode( ':', $box['id'] ); //if ( count($role_attribs) != 3 ) // return; $object_id = isset($object->ID) ? $object->ID : 0; $object_type = cr_find_post_type(); $this->init_item_roles_ui(); $this->item_roles_ui->draw_object_roles_content('post', $object_type, $box['id'], $object_id, false, $object); }
function flt_wp_dropdown_users($wp_output) { // just filter Post Author dropdown if (!strpos($wp_output, "name='post_author_override'")) { return $wp_output; } // this is meant to filter the post author selection if (!is_admin()) { return $wp_output; } // if (even after our blogcap tinkering) the author list is already locked due to insufficient blog-wide caps, don't mess if (!($pos = strpos($wp_output, '<option'))) { return $wp_output; } if (!strpos($wp_output, '<option', $pos + 1)) { return $wp_output; } global $wpdb, $scoper; $last_query = $wpdb->last_query; if (!($object_type = cr_find_post_type())) { return $wp_output; } if (!($post_type_obj = get_post_type_object($object_type))) { return $wp_output; } global $current_user; $is_ngg_edit = strpos($_SERVER['REQUEST_URI'], 'nggallery-manage-gallery'); if (!$is_ngg_edit) { $src_name = 'post'; $object_id = scoper_get_object_id('post', $object_type); // only modify the default authors list if current user has Editor role for the current post/page $have_cap = cr_user_can($post_type_obj->cap->edit_others_posts, $object_id, 0, array('require_full_object_role' => true)); } else { $src_name = 'ngg_gallery'; $object_id = $_REQUEST['gid']; $have_cap = !empty($current_user->allcaps[$post_type_obj->cap->edit_others_posts]); // $post_type_obj defaults to 'post' type on NGG Manage Gallery page } //if ( ! $have_cap ) // return $wp_output; $orderpos = strpos($last_query, 'ORDER BY'); $orderby = $orderpos ? substr($last_query, $orderpos) : ''; if (!strpos($orderby, 'display_name')) { // sanity check in case the last_query buffer gets messed up $orderby = ''; } $id_in = $id_not_in = $show_option_all = $show_option_none = ''; $pos = strpos($last_query, 'AND ID IN('); if ($pos) { $pos_close = strpos($last_query, ')', $pos); if ($pos_close) { $id_in = substr($last_query, $pos, $pos_close - $pos + 1); } } $pos = strpos($last_query, 'AND ID NOT IN('); if ($pos) { $pos_close = strpos($last_query, ')', $pos); if ($pos_close) { $id_not_in = substr($last_query, $pos, $pos_close - $pos + 1); } } $search = "<option value='0'>"; $pos = strpos($wp_output, $search . __awp('Any')); if ($pos) { $pos_close = strpos($wp_output, '</option>', $pos); if ($pos_close) { $show_option_all = substr($wp_output, $pos + strlen($search), $pos_close - $pos - strlen($search)); } } $search = "<option value='-1'>"; $pos = strpos($wp_output, $search . __awp('None')); if ($pos) { $pos_close = strpos($wp_output, '</option>', $pos); if ($pos_close) { $show_option_none = substr($wp_output, $pos + strlen($search), $pos_close - $pos - strlen($search)); } } $search = "<select name='"; $pos = strpos($wp_output, $search); if (false !== $pos) { $pos_close = strpos($wp_output, "'", $pos + strlen($search)); if ($pos_close) { $name = substr($wp_output, $pos + strlen($search), $pos_close - $pos - strlen($search)); } } $search = " id='"; $multi = !strpos($wp_output, $search); // beginning with WP 2.7, some users dropdowns lack id attribute $search = " class='"; $pos = strpos($wp_output, $search); if ($pos) { $pos_close = strpos($wp_output, "'", $pos + strlen($search)); if ($pos_close) { $class = substr($wp_output, $pos + strlen($search), $pos_close - $pos - strlen($search)); } } $search = " selected='selected'"; $pos = strpos($wp_output, $search); if ($pos) { $search = "<option value='"; $str_left = substr($wp_output, 0, $pos); $pos = strrpos($str_left, $search); //back up to previous option tag $pos_close = strpos($wp_output, "'", $pos + strlen($search)); if ($pos_close) { $selected = substr($wp_output, $pos + strlen($search), $pos_close - ($pos + strlen($search))); } } if (empty($selected)) { $selected = $current_user->ID; } // precaution prevents default-selection of non-current user // Role Scoper filter application $where = "{$id_in} {$id_not_in}"; $args = array(); $args['where'] = $where; $args['orderby'] = $orderby; if ($object_id > 0) { if ($current_author = $scoper->data_sources->get_from_db('owner', $src_name, $object_id)) { $force_user_id = $current_author; } } else { $force_user_id = $current_user->ID; } if ($have_cap) { if ($force_user_id) { $args['preserve_or_clause'] = " uro.user_id = '{$force_user_id}'"; } $users = $scoper->users_who_can($post_type_obj->cap->edit_posts, COLS_ID_DISPLAYNAME_RS, 'post', $object_id, $args); } else { $display_name = $wpdb->get_var("SELECT display_name FROM {$wpdb->users} WHERE ID = '{$force_user_id}'"); $users = array((object) array('ID' => $force_user_id, 'display_name' => $display_name)); } if (empty($users)) { // sanity check: users_who_can should always return Administrators if ($admin_roles = awp_administrator_roles()) { $users = scoper_get_results("SELECT DISTINCT ID, display_name FROM {$wpdb->users} INNER JOIN {$wpdb->user2role2object_rs} AS uro ON uro.user_id = {$wpdb->users}.ID AND uro.scope = 'blog' AND uro.role_type = 'wp' AND uro.role_name IN ('" . implode("','", $admin_roles) . "')"); } else { return $wp_output; } // the user data must be messed up } $show = 'display_name'; // no way to back this out // ----------- begin wp_dropdown_users code copy (from WP 2.7) ------------- $id = $multi ? "" : "id='{$name}'"; $output = "<select name='{$name}' {$id} class='{$class}'>\n"; if ($show_option_all) { $output .= "\t<option value='0'>{$show_option_all}</option>\n"; } if ($show_option_none) { $output .= "\t<option value='-1'>{$show_option_none}</option>\n"; } foreach ((array) $users as $user) { $user->ID = (int) $user->ID; $_selected = $user->ID == $selected ? " selected='selected'" : ''; $display = !empty($user->{$show}) ? $user->{$show} : '(' . $user->user_login . ')'; $output .= "\t<option value='{$user->ID}'{$_selected}>" . esc_html($display) . "</option>\n"; } $output .= "</select>"; // ----------- end wp_dropdown_users code copy (from WP 2.7) ------------- return $output; }
function flt_get_others_drafts($results) { global $wpdb, $current_user, $scoper; // buffer titles in case they were filtered previously $titles = scoper_get_property_array($results, 'ID', 'post_title'); // WP 2.3 added pending status, but no new hook or hook argument $draft_query = strpos($wpdb->last_query, 'draft'); $pending_query = strpos($wpdb->last_query, 'pending'); if ($draft_query && $pending_query) { $status_clause = "AND ( post_status = 'draft' OR post_status = 'pending' )"; } elseif ($draft_query) { $status_clause = "AND post_status = 'draft'"; } else { $status_clause = "AND post_status = 'pending'"; } $object_type = cr_find_post_type(); if (!$object_type) { $object_type = 'post'; } if (!($otype_val = $scoper->data_sources->member_property('post', 'object_types', $object_type, 'val'))) { $otype_val = $object_type; } $qry = "SELECT ID, post_title, post_author FROM {$wpdb->posts} WHERE post_type = '{$otype_val}' AND post_author != '{$current_user->ID}' {$status_clause}"; $qry = apply_filters('objects_request_rs', $qry, 'post', '', ''); $items = scoper_get_results($qry); // restore buffered titles in case they were filtered previously scoper_restore_property_array($items, $titles, 'ID', 'post_title'); return $items; }
function cr_find_object_type($src_name, $object = '') { if ('post' == $src_name) { return cr_find_post_type($object); } global $scoper; $src = $scoper->data_sources->get($src_name); $object_id = is_object($object) ? $src->cols->id : $object; return sanitize_key($scoper->data_sources->detect('type', $src_name, $object_id)); }
function get_terms_reqd_caps($taxonomy, $operation = '', $is_term_admin = false) { global $pagenow; if (!($src_name = $this->taxonomies->member_property($taxonomy, 'object_source'))) { if (taxonomy_exists($taxonomy)) { $src_name = 'post'; } } $return_caps = array(); $is_term_admin = $is_term_admin || in_array($pagenow, array('edit-tags.php')) || ('nav_menu' == $taxonomy && 'nav-menus.php' == $pagenow || 'admin-ajax.php' == $pagenow && (!empty($_REQUEST['action']) && in_array($_REQUEST['action'], array('add-menu-item', 'menu-locations-save')))); // possible TODO: abstract for non-WP taxonomies if ($is_term_admin) { // query pertains to the management of terms if ('post' == $src_name) { $taxonomy_obj = get_taxonomy($taxonomy); $return_caps[$taxonomy] = array($taxonomy_obj->cap->manage_terms); } elseif ('link_category' == $taxonomy) { $return_caps[$taxonomy] = array('manage_categories'); } else { global $scoper; $cap_defs = $scoper->cap_defs->get_matching($src_name, $taxonomy, OP_ADMIN_RS); $return_caps[$taxonomy] = $cap_defs ? array_keys($cap_defs) : array(); } } else { // query pertains to reading or editing content within certain terms, or adding terms to content $base_caps_only = true; if ('post' == $src_name) { if (!$operation) { $operation = $this->is_front() || 'profile.php' == $pagenow || is_admin() && 's2' == $GLOBALS['plugin_page'] ? 'read' : 'edit'; } // hack to support subscribe2 categories checklist $status = 'read' == $operation ? 'publish' : 'draft'; // terms query should be limited to a single object type for post.php, post-new.php, so only return caps for that object type (TODO: do this in wp-admin regardless of URI ?) if (in_array($pagenow, array('post.php', 'post-new.php'))) { $object_type = cr_find_post_type(); } } else { if (!$operation) { $operation = $this->is_front() ? 'read' : 'edit'; } $status = ''; } // The return array will indicate term role enable / disable, as well as associated capabilities if (!empty($object_type)) { $check_object_types = array($object_type); } else { if ($check_object_types = (array) $this->data_sources->member_property($src_name, 'object_types')) { $check_object_types = array_keys($check_object_types); } } if ('post' == $src_name) { $use_post_types = scoper_get_option('use_post_types'); } $enabled_object_types = array(); foreach ($check_object_types as $_object_type) { if ($use_term_roles = scoper_get_otype_option('use_term_roles', $src_name, $_object_type)) { if (!empty($use_term_roles[$taxonomy])) { if ('post' != $src_name || !empty($use_post_types[$_object_type])) { $enabled_object_types[] = $_object_type; } } } } foreach ($enabled_object_types as $object_type) { $return_caps[$object_type] = cr_get_reqd_caps($src_name, $operation, $object_type, $status, $base_caps_only); } } return $return_caps; }
function awp_post_type_from_uri() { return cr_find_post_type(); }
function flt_objects_results($results, $src_name, $object_types, $args = array()) { if (!$object_types || is_array($object_types) && count($object_types) > 1) { $object_type = cr_find_post_type(); } else { $object_type = strval($object_types); } if ('edit.php' == $GLOBALS['pagenow'] && !is_content_administrator_rs()) { $post_type_obj = get_post_type_object($object_type); if (!empty($post_type_obj->hierarchical)) { // ScoperAncestry class is loaded by hardway_rs.php $ancestors = ScoperAncestry::get_page_ancestors(); // array of all ancestor IDs for keyed page_id, with direct parent first $args = array('remap_parents' => false); ScoperHardway::remap_tree($results, $ancestors, 'ID', 'post_parent', $args); } } if ($this->scoper->is_front() && empty($this->skip_teaser)) { if ($tease_otypes = $this->_get_teaser_object_types($src_name, $object_types, $args)) { require_once dirname(__FILE__) . '/teaser_rs.php'; $args['force_teaser'] = true; return ScoperTeaser::posts_teaser_prep_results($results, $tease_otypes, $args); } // won't do anything unless teaser is enabled for object type(s) //$results = apply_filters('objects_teaser_pre_results_rs', $results, 'post', $object_type, array('force_teaser' => true)); } return $results; }
function _flt_last_resort_query($query) { // no recursion if (scoper_querying_db() || $GLOBALS['cap_interceptor']->in_process) { return $query; } global $wpdb, $pagenow, $scoper; $posts = $wpdb->posts; // Search on query portions to make this as forward-compatible as possible. // Important to include " FROM table WHERE " as a strpos requirement because scoped queries (which should not be further altered here) will insert a JOIN clause // strpos search for "ELECT " rather than "SELECT" so we don't have to distinguish 0 from false // wp_count_posts() : // SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s $matches = array(); if (strpos($query, "ELECT post_status, COUNT( * ) AS num_posts ") && preg_match("/FROM\\s*{$posts}\\s*WHERE post_type\\s*=\\s*'([^ ]+)'/", $query, $matches)) { $_post_type = !empty($matches[1]) ? $matches[1] : cr_find_post_type(); if ($_post_type) { global $current_user; foreach (get_post_stati(array('private' => true)) as $_status) { $query = str_replace("AND (post_status != '{$_status}' OR ( post_author = '{$current_user->ID}' AND post_status = '{$_status}' ))", '', $query); } $query = str_replace("post_status", "{$posts}.post_status", $query); $query = apply_filters('objects_request_rs', $query, 'post', $_post_type, array('objrole_revisions_clause' => true)); // as of WP 3.0.1, additional queries triggered by objects_request filter breaks all subsequent filters which would have operated on this query if (defined('RVY_VERSION')) { if (class_exists('RevisionaryAdminHardway_Ltd')) { $query = RevisionaryAdminHardway_Ltd::flt_last_resort_query($query); } $query = RevisionaryAdminHardway::flt_include_pending_revisions($query); } } return $query; } // parent_dropdown() : // SELECT ID, post_parent, post_title FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'page' ORDER BY menu_order if ('admin.php' == $pagenow) { if (strpos($query, "ELECT ID, post_parent, post_title") && strpos($query, "FROM {$posts} WHERE post_parent =") && function_exists('parent_dropdown')) { $page_temp = ''; $object_id = $scoper->data_sources->detect('id', 'post'); if ($object_id) { $page_temp = get_post($object_id); } if (empty($page_temp) || !isset($page_temp->post_parent) || $page_temp->post_parent) { require_once SCOPER_ABSPATH . '/hardway/hardway-parent-legacy_rs.php'; $output = ScoperHardwayParentLegacy::dropdown_pages(); echo $output; } $query = "SELECT ID, post_parent FROM {$posts} WHERE 1=2"; return $query; } } // Media Library - unattached // // WP_MediaListTable::get_views() : // SELECT COUNT( * ) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_parent < 1 if (strpos($query, "post_type = 'attachment'") && strpos($query, "post_parent < 1") && strpos($query, '* FROM')) { if ($where_pos = strpos($query, 'WHERE ')) { // optionally hide other users' unattached uploads, but not from blog-wide Editors if (!scoper_get_option('admin_others_unattached_files') && !$scoper->user_can_edit_blogwide('post', '', array('require_others_cap' => true, 'status' => 'publish'))) { global $current_user; $author_clause = "AND {$wpdb->posts}.post_author = '{$current_user->ID}'"; $query = str_replace("post_type = 'attachment'", "post_type = 'attachment' {$author_clause}", $query); return $query; } } } // wp_count_attachments() : //SELECT post_mime_type, COUNT( * ) AS num_posts FROM wp_trunk_posts WHERE post_type = 'attachment' GROUP BY post_mime_type if (strpos($query, "post_type = 'attachment'") && 0 === strpos($query, "SELECT ")) { if ($where_pos = strpos($query, 'WHERE ')) { if (!defined('SCOPER_ALL_UPLOADS_EDITABLE')) { // note: this constant actually just prevents Media Library filtering, falling back to WP Roles for attachment editability and leaving uneditable uploads viewable in Library static $att_sanity_count = 0; if ($att_sanity_count > 5) { // TODO: why does this apply filtering to 300+ queries on at least one MS installation? return $query; } $att_sanity_count++; $admin_others_attached = scoper_get_option('admin_others_attached_files'); $admin_others_unattached = scoper_get_option('admin_others_unattached_files'); if (!$admin_others_attached || !$admin_others_unattached) { $can_edit_others_blogwide = $scoper->user_can_edit_blogwide('post', '', array('require_others_cap' => true, 'status' => 'publish')); } global $wpdb, $current_user; // optionally hide other users' unattached uploads, but not from blog-wide Editors if ($admin_others_unattached || $can_edit_others_blogwide) { $author_clause = ''; } else { $author_clause = "AND {$wpdb->posts}.post_author = '{$current_user->ID}'"; } if (!defined('SCOPER_BLOCK_UNATTACHED_UPLOADS') || !SCOPER_BLOCK_UNATTACHED_UPLOADS) { $unattached_clause = "( {$wpdb->posts}.post_parent = 0 {$author_clause} ) OR"; } else { $unattached_clause = ''; } $attached_clause = $admin_others_attached || $can_edit_others_blogwide ? '' : "AND {$wpdb->posts}.post_author = '{$current_user->ID}'"; $parent_query = "SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} WHERE 1=1"; $parent_query = apply_filters('objects_request_rs', $parent_query, 'post'); $where_insert = "( {$unattached_clause} ( {$wpdb->posts}.post_parent IN ({$parent_query}) {$attached_clause} ) ) AND "; $query = substr($query, 0, $where_pos + strlen('WHERE ')) . $where_insert . substr($query, $where_pos + strlen('WHERE ')); } return $query; } } // admin-ajax.php 'find_posts' : // SELECT ID, post_title, post_status, post_date FROM $wpdb->posts WHERE post_type = '$what' AND post_status IN ('draft', 'publish') AND ($search) ORDER BY post_date_gmt DESC LIMIT 50 if (strpos($query, "ELECT ID, post_title, post_status, post_date FROM")) { if (!empty($_POST['post_type'])) { $query = apply_filters('objects_request_rs', $query, 'post', $_POST['post_type']); } } return $query; }
function admin_head() { global $pagenow, $plugin_page_cr; echo '<link rel="stylesheet" href="' . SCOPER_URLPATH . '/admin/role-scoper.css" type="text/css" />' . "\n"; if ('rs-about' == $plugin_page_cr) { echo '<link rel="stylesheet" href="' . SCOPER_URLPATH . '/admin/about/about.css" type="text/css" />' . "\n"; } if (in_array($pagenow, array('post.php', 'post-new.php'))) { $src_name = 'post'; $object_type = cr_find_post_type(); } elseif (isset($_GET['src_name']) && isset($_GET['object_type'])) { $src_name = sanitize_key($_GET['src_name']); $object_type = sanitize_key($_GET['object_type']); } if (!empty($object_type)) { // dynamically set checkbox titles for user/group object role selection $src = $this->scoper->data_sources->get($src_name); $otype_def = $this->scoper->data_sources->member_property($src_name, 'object_types', $object_type); if (!empty($src) && !empty($src->cols->parent) && empty($otype_def->ignore_object_hierarchy)) { if (!empty($otype_def->labels)) { $obj_title = sprintf(__('assign role for this %s', 'scoper'), agp_strtolower($otype_def->labels->singular_name)); $child_title = sprintf(__('assign role for sub-%s', 'scoper'), agp_strtolower($otype_def->labels->name)); $js_params = "var role_for_object_title = '{$obj_title}';" . "var role_for_children_title = '{$child_title}';"; // TODO: replace some of this JS with equivalent JQuery echo "\n" . '<script type="text/javascript">' . $js_params . '</script>'; echo "\n" . "<script type='text/javascript' src='" . SCOPER_URLPATH . "/admin/rs-objrole-cbox-maint.js'></script>"; } } } add_filter('contextual_help_list', array(&$this, 'flt_contextual_help_list'), 10, 2); if (0 === strpos($plugin_page_cr, 'rs-') && strpos($plugin_page_cr, 'roles')) { // add Ajax goodies we need for role duration/content date limit editing Bulk Role Admin if (!awp_ver('3.4')) { wp_print_scripts(array('page')); } require_once dirname(__FILE__) . '/admin_lib-bulk_rs.php'; ScoperAdminBulkLib::date_limits_js(); } // TODO: replace some of this JS with equivalent JQuery echo "\n" . "<script type='text/javascript' src='" . SCOPER_URLPATH . "/admin/agapetry.js'></script>"; echo "\n" . "<script type='text/javascript' src='" . SCOPER_URLPATH . "/admin/role-scoper.js'></script>"; if (scoper_get_option('group_ajax') && (in_array($pagenow, array('user-edit.php', 'profile.php')) || 'rs-groups' == $plugin_page_cr)) { global $scoper_user_search; if ('rs-groups' == $plugin_page_cr) { $agent_type = 'users'; $agent_id = isset($_GET['id']) ? $_GET['id'] : 0; } else { $agent_type = 'groups'; if ('profile.php' == $pagenow) { global $current_user; $agent_id = $current_user->ID; } else { $agent_id = (int) $_GET['user_id']; } } require_once dirname(__FILE__) . '/user_search_ui_rs.php'; $scoper_user_search = new ScoperUserSearch($agent_type); $scoper_user_search->output_js($agent_type, $agent_id); } }
function get_from_uri($what, $src, $object_type = '') { // workaround for WP 3.0, which uses post.php, edit.php, post-new.php for all post types if ('type' == $what && 'post' == $src->name) { return cr_find_post_type(); } if (!($src = $this->get($src))) { return; } /* rs_errlog(''); rs_errlog("get $what from_uri"); rs_errlog( 'URI: '. $_SERVER['REQUEST_URI'] ); */ // Try to pull the desired value from URI variables, // using data_sources definition to convert the abstract $what into URI variable name $varname = $this->get_varname('uri', $what, $src, $object_type); //rs_errlog('varname: '. $varname); if (isset($_GET[$varname])) { return $_GET[$varname]; } else { if (isset($src->uri_vars_alt->{$what})) { $vars_alt = (array) $src->uri_vars_alt->{$what}; foreach ($vars_alt as $varname_alt) { if (isset($_GET[$varname_alt])) { return $_GET[$varname_alt]; } } } } }
function flt_get_tags($results, $taxonomies, $args) { if (!is_array($taxonomies)) { $taxonomies = (array) $taxonomies; } if ('post_tag' != $taxonomies[0] || count($taxonomies) > 1) { return $results; } global $wpdb; $defaults = array('exclude' => '', 'include' => '', 'number' => '', 'offset' => '', 'slug' => '', 'name__like' => '', 'search' => '', 'hide_empty' => true); $args = wp_parse_args($args, $defaults); extract($args, EXTR_SKIP); if ('ids' == $fields || !$hide_empty) { return $results; } global $scoper, $current_rs_user; $filter_key = has_filter('list_terms_exclusions') ? serialize($GLOBALS['wp_filter']['list_terms_exclusions']) : ''; $ckey = md5(serialize(compact(array_keys($defaults))) . serialize($taxonomies) . $filter_key); $cache_flag = 'rs_get_terms'; if ($cache = $current_rs_user->cache_get($cache_flag)) { if (isset($cache[$ckey])) { return apply_filters('get_tags_rs', $cache[$ckey], 'post_tag', $args); } } //------------ WP argument application code from get_terms(), with hierarchy-related portions removed ----------------- // // NOTE: must change 'tt.count' to 'count' in orderby and hide_empty settings // Also change default orderby to name // $where = ''; $inclusions = ''; if (!empty($include)) { $exclude = ''; $exclude_tree = ''; $interms = wp_parse_id_list($include); if (count($interms)) { foreach ((array) $interms as $interm) { if (empty($inclusions)) { $inclusions = ' AND ( t.term_id = ' . intval($interm) . ' '; } else { $inclusions .= ' OR t.term_id = ' . intval($interm) . ' '; } } } } if (!empty($inclusions)) { $inclusions .= ')'; } $where .= $inclusions; $exclusions = ''; if (!empty($exclude)) { $exterms = wp_parse_id_list($exclude); if (count($exterms)) { foreach ((array) $exterms as $exterm) { if (empty($exclusions)) { $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; } else { $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; } } } } if (!empty($exclusions)) { $exclusions .= ')'; } $exclusions = apply_filters('list_terms_exclusions', $exclusions, $args); $where .= $exclusions; if (!empty($slug)) { $slug = sanitize_title($slug); $where .= " AND t.slug = '{$slug}'"; } if (!empty($name__like)) { $where .= " AND t.name LIKE '{$name__like}%'"; } // don't limit the query results when we have to descend the family tree if (!empty($number)) { if ($offset) { $limit = 'LIMIT ' . $offset . ',' . $number; } else { $limit = 'LIMIT ' . $number; } } else { $limit = ''; } if (!empty($search)) { $search = like_escape($search); $where .= " AND (t.name LIKE '%{$search}%')"; } // ------------- end get_terms() argument application code -------------- $post_type = cr_find_post_type(); // embedded select statement for posts ID IN clause $posts_qry = "SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} WHERE 1=1"; $posts_qry = apply_filters('objects_request_rs', $posts_qry, 'post', $post_type, array('skip_teaser' => true)); $qry = "SELECT DISTINCT t.*, tt.*, COUNT(p.ID) AS count FROM {$wpdb->terms} AS t" . " INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = t.term_id AND tt.taxonomy = 'post_tag'" . " INNER JOIN {$wpdb->term_relationships} AS tagr ON tagr.term_taxonomy_id = tt.term_taxonomy_id" . " INNER JOIN {$wpdb->posts} AS p ON p.ID = tagr.object_id WHERE p.ID IN ({$posts_qry})" . " {$where} GROUP BY t.term_id ORDER BY count DESC {$limit}"; // must hardcode orderby clause to always query top tags $results = scoper_get_results($qry); $cache[$ckey] = $results; $current_rs_user->cache_set($cache, $cache_flag); $results = apply_filters('get_tags_rs', $results, 'post_tag', $args); return $results; }
function ui_hide_admin_divs() { if (!in_array($GLOBALS['pagenow'], array('post.php', 'post-new.php'))) { return; } if (!($object_type = cr_find_post_type())) { return; } // For this data source, is there any html content to hide from non-administrators? $option_type = 'page' == $object_type ? 'page' : 'post'; $css_ids = scoper_get_otype_option('admin_css_ids', 'post', $option_type); $css_ids = str_replace(' ', '', $css_ids); $css_ids = str_replace(',', ';', $css_ids); $css_ids = explode(';', $css_ids); // option storage is as semicolon-delimited string if (empty($css_ids)) { return; } $object_id = scoper_get_object_id('post'); $can_edit_blogwide = $this->scoper->user_can_edit_blogwide('post', $object_type); $blogwide_requirement = scoper_get_option('hide_non_editor_admin_divs'); if ('admin_option' == $blogwide_requirement) { $blogwide_requirement_met = is_option_administrator_rs(); } elseif ('admin_user' == $blogwide_requirement) { $blogwide_requirement_met = is_user_administrator_rs(); } elseif ('admin_content' == $blogwide_requirement) { $blogwide_requirement_met = is_content_administrator_rs(); } elseif ('editor' == $blogwide_requirement) { $blogwide_requirement_met = $this->scoper->user_can_edit_blogwide('post', $object_type, array('status' => 'publish', 'require_others_cap' => true)); } elseif ('author' == $blogwide_requirement) { $blogwide_requirement_met = $this->scoper->user_can_edit_blogwide('post', $object_type, array('status' => 'publish')); } elseif ($blogwide_requirement) { $blogwide_requirement_met = $can_edit_blogwide; } else { $blogwide_requirement_met = true; } if ($can_edit_blogwide && $blogwide_requirement_met) { // don't hide anything if a user with sufficient blog-wide role is creating a new object if (!$object_id) { return; } if (!($object = $this->scoper->data_sources->get_object('post', $object_id))) { return; } if (empty($object->post_date)) { // don't prevent the full editing of new posts/pages return; } // don't hide anything if a user with sufficient blog-wide role is editing their own object /* global $current_user; if ( empty($object->post_author) || ( $object->post_author == $current_user->ID) ) return; */ } if ($blogwide_requirement && !$blogwide_requirement_met || !$this->scoper_admin->user_can_admin_object('post', $object_type, $object_id, '', '', true)) { echo "\n<style type='text/css'>\n<!--\n"; $removeable_metaboxes = apply_filters('scoper_removeable_metaboxes', array('categorydiv', 'tagsdiv-post_tag', 'postcustom', 'pagecustomdiv', 'authordiv', 'pageauthordiv', 'trackbacksdiv', 'revisionsdiv', 'pending_revisions_div', 'future_revisionsdiv')); foreach ($css_ids as $id) { if (in_array($id, $removeable_metaboxes)) { // thanks to piemanek for tip on using remove_meta_box for any core admin div remove_meta_box($id, $object_type, 'normal'); remove_meta_box($id, $object_type, 'advanced'); } else { // hide via CSS if the element is not a removeable metabox echo "#{$id} { display: none !important; }\n"; // this line adapted from Clutter Free plugin by Mark Jaquith } } echo "-->\n</style>\n"; } }
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; } } } }