Ejemplo n.º 1
0
 public static function inherit_parent_exceptions($item_id, $args = array())
 {
     $defaults = array('via_item_source' => '', 'via_item_type' => '', 'set_parent' => '', 'last_parent' => '', 'is_new' => true);
     extract(array_merge($defaults, $args), EXTR_SKIP);
     $is_new_term = 'term' != $via_item_source ? false : !empty($_REQUEST['action']) && 'add-tag' == $_REQUEST['action'];
     // don't execute this action handler more than one per post save (may be called directly on pre-save cap check)
     static $did_items;
     if ('post' == $via_item_source) {
         if (!isset($did_items)) {
             $did_items = array();
         }
         if (isset($did_items[$item_id])) {
             return;
         }
         $did_items[$item_id] = 1;
     }
     if (!apply_filters('pp_do_inherit_parent_exceptions', true, $item_id, $args)) {
         return;
     }
     // Inherit exceptions from new parent post/term, but only for new items or if parent is changed
     if (isset($set_parent) && $set_parent != $last_parent || $is_new_term) {
         // retain all explicitly selected exceptions
         global $wpdb;
         $descendant_ids = pp_get_descendant_ids($via_item_source, $item_id);
         if ($descendant_ids && 'term' == $via_item_source) {
             $descendant_ids = pp_termid_to_ttid($descendant_ids, $via_item_type);
         }
         // clear previously propagated role assignments for this item and its branch of sub-items
         if (!$is_new) {
             _pp_clear_exceptions($via_item_source, $item_id, array('inherited_only' => true));
             _pp_clear_exceptions($via_item_source, $descendant_ids, array('inherited_only' => true));
         }
         // assign propagating exceptions from new parent
         if ($set_parent) {
             $id_clause = "AND i.item_id IN ('" . implode("','", array_merge($descendant_ids, (array) $item_id)) . "')";
             $retain_exceptions = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->ppc_exception_items} AS i INNER JOIN {$wpdb->ppc_exceptions} AS e ON e.exception_id = i.exception_id WHERE i.assign_for = 'item' AND i.inherited_from = '0' AND e.via_item_source = %s {$id_clause}", $via_item_source));
             if ('term' == $via_item_source) {
                 $parent_term = get_term($set_parent, $via_item_type);
                 $set_parent = $parent_term->term_taxonomy_id;
             }
             // propagate exception from new parent to this item and its branch of sub-items
             $_args = compact('retain_exceptions', 'force_for_item_type');
             $_args['parent_exceptions'] = _pp_get_parent_exceptions($via_item_source, $item_id, $set_parent);
             $any_inserts = _pp_inherit_parent_exceptions($via_item_source, $item_id, $set_parent, $_args);
             foreach ($descendant_ids as $_descendant_id) {
                 $any_inserts = $any_inserts || _pp_inherit_parent_exceptions($via_item_source, $_descendant_id, $set_parent, $_args);
             }
         }
     }
     // endif new parent selection (or new item)
     return !empty($any_inserts);
 }
Ejemplo n.º 2
0
 public static function insert_exceptions($mod_type, $operation, $via_item_source, $via_item_type, $for_item_source, $for_item_type, $item_id, $agent_type, $agents, $args)
 {
     $defaults = array('assign_for' => 'item', 'remove_assignments' => false, 'for_item_status' => '', 'mod_type' => '', 'inherited_from' => array(), 'is_auto_insertion' => false);
     // auto_insertion arg set for propagation from parent objects
     $args = array_merge($defaults, (array) $args);
     extract($args, EXTR_SKIP);
     if (!$agents) {
         return;
     }
     global $wpdb, $current_user;
     $updated_items = array();
     // for use with do_action hook
     $updated_items[] = $item_id;
     $assigner_id = $current_user->ID;
     $operation = pp_sanitize_key($operation);
     $via_item_source = pp_sanitize_key($via_item_source);
     $for_item_source = pp_sanitize_key($for_item_source);
     $for_item_type = pp_sanitize_key($for_item_type);
     $item_id = (int) $item_id;
     $agent_type = pp_sanitize_key($agent_type);
     $mod_type = pp_sanitize_key($mod_type);
     $via_item_type = pp_sanitize_key($via_item_type);
     $for_item_status = pp_sanitize_csv($for_item_status);
     $assign_for = pp_sanitize_key($assign_for);
     if ('children' == $assign_for) {
         if ('term' == $via_item_source) {
             $descendant_ids = array();
             if ($_term = $wpdb->get_row("SELECT term_id, taxonomy FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id = '{$item_id}' LIMIT 1")) {
                 if ($_term_ids = pp_get_descendant_ids('term', $_term->term_id)) {
                     $descendant_ids = pp_termid_to_ttid($_term_ids, $_term->taxonomy);
                 }
             }
         } else {
             $descendant_ids = pp_get_descendant_ids($via_item_source, $item_id, array('include_attachments' => false));
             // don't propagate page exceptions to attachments
         }
         if ($descendant_ids) {
             // TODO: reinstate this?
             /*
             global $pp_admin;
             
             if ( ! $is_auto_insertion ) {
             	// don't allow a page parent change to modify role assignments for a descendant object which the current user can't administer
             	$remove_ids = array();
             	foreach ( $descendant_ids as $id ) {
             		if ( 'term' == $scope ) {
             			if ( ! $pp_admin->user_can_admin_terms($item_source, $id) )  // TODO: add $args with 'taxonomy'
             				$remove_ids []= $id;
             		} else {
             			if ( ! $pp_admin->user_can_admin_object( $item_source, $id ) )
             				$remove_ids []= $id;
             		}
             	}
             
             	$descendant_ids = array_diff( $descendant_ids, $remove_ids );
             }
             */
             $descendant_id_csv = implode("','", $descendant_ids);
         }
     }
     // Before inserting an exception, delete any overlooked old exceptions for the same src/type/status.
     $match_cols = compact('mod_type', 'for_item_source', 'for_item_status', 'operation', 'agent_type', 'via_item_source', 'via_item_type');
     $_clauses = array();
     foreach ($match_cols as $col => $val) {
         $_clauses[] = "{$col} = '{$val}'";
     }
     $qry_exc_select_base = "SELECT * FROM {$wpdb->ppc_exceptions} WHERE " . implode(' AND ', $_clauses);
     $qry_exc_select_type_base = "SELECT for_item_type, exception_id FROM {$wpdb->ppc_exceptions} WHERE " . implode(' AND ', $_clauses);
     $insert_exc_data = $match_cols;
     $insert_exc_data['assigner_id'] = $assigner_id;
     $qry_item_select_base = "SELECT eitem_id FROM {$wpdb->ppc_exception_items} WHERE assign_for = '{$assign_for}' AND item_id = '{$item_id}'";
     $qry_item_delete_base = "SELECT eitem_id FROM {$wpdb->ppc_exception_items} WHERE 1=1";
     foreach (array_keys($agents) as $agent_id) {
         $agent_id = (int) $agent_id;
         // first, retrieve or create the pp_exceptions record for this user/group and src,type,status
         if (!($exc = $wpdb->get_row("{$qry_exc_select_base} AND for_item_type = '{$for_item_type}' AND agent_id = '{$agent_id}'"))) {
             $insert_exc_data['agent_id'] = $agent_id;
             $insert_exc_data['for_item_type'] = $for_item_type;
             $wpdb->insert($wpdb->ppc_exceptions, $insert_exc_data);
             $exception_id = $wpdb->insert_id;
         } else {
             $exception_id = $exc->exception_id;
         }
         $this_inherited_from = isset($inherited_from[$agent_id]) ? $inherited_from[$agent_id] : 0;
         // delete any existing items for this exception_id
         if ($eitem_ids = $wpdb->get_col($qry_item_select_base . " AND exception_id = '{$exception_id}'")) {
             self::remove_exception_items_by_id($eitem_ids);
         }
         // insert exception items
         $item_data = compact('item_id', 'assign_for', 'exception_id', 'assigner_id');
         $item_data['inherited_from'] = $this_inherited_from;
         $wpdb->insert($wpdb->ppc_exception_items, $item_data);
         do_action('pp_inserted_exception_item', array_merge((array) $exc, $item_data));
         $assignment_id = $wpdb->insert_id;
         // insert exception for all descendant items
         if ('children' == $assign_for && $descendant_ids) {
             if (!$this_inherited_from) {
                 $this_inherited_from = (int) $assignment_id;
                 //$role_arr['inherited_from'] = $this_inherited_from;
             }
             $exceptions_by_type = array();
             $_results = $wpdb->get_results("{$qry_exc_select_type_base} AND for_item_type = '{$for_item_type}' AND agent_id = '{$agent_id}'");
             foreach ($_results as $row) {
                 $exceptions_by_type[$row->for_item_type] = $row->exception_id;
             }
             if ('term' == $via_item_source && taxonomy_exists($for_item_type)) {
                 // need to allow for descendants of a different post type than parent
                 $descendant_types = $wpdb->get_results("SELECT term_taxonomy_id, taxonomy AS for_item_type FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id IN ('" . implode("','", $descendant_ids) . "')", OBJECT_K);
             } elseif ('post' == $via_item_source) {
                 $descendant_types = $wpdb->get_results("SELECT ID, post_type AS for_item_type FROM {$wpdb->posts} WHERE ID IN ('" . implode("','", $descendant_ids) . "')", OBJECT_K);
             } else {
                 $descendant_types = array();
             }
             foreach ($descendant_ids as $id) {
                 if ($for_item_type) {
                     // allow for descendants with post type different from parent
                     if (!isset($descendant_types[$id])) {
                         $child_for_item_type = $for_item_type;
                         // if child type could not be determined, assume parent type
                     } elseif ('revision' == $descendant_types[$id]->for_item_type) {
                         continue;
                     } else {
                         $child_for_item_type = $descendant_types[$id]->for_item_type;
                     }
                 } else {
                     $child_for_item_type = '';
                 }
                 if (!isset($exceptions_by_type[$child_for_item_type])) {
                     $insert_exc_data['agent_id'] = $agent_id;
                     $insert_exc_data['for_item_type'] = $child_for_item_type;
                     $wpdb->insert($wpdb->ppc_exceptions, $insert_exc_data);
                     $exceptions_by_type[$child_for_item_type] = $wpdb->insert_id;
                 }
                 $child_exception_id = $exceptions_by_type[$child_for_item_type];
                 // Don't overwrite an explicitly assigned exception with a propagated exception
                 if (!defined('PP_FORCE_EXCEPTION_OVERWRITE') || !PP_FORCE_EXCEPTION_OVERWRITE) {
                     $have_direct_assignments = $wpdb->get_col("SELECT item_id FROM {$wpdb->ppc_exception_items} WHERE exception_id = '{$child_exception_id}' AND inherited_from = '0' AND item_id IN ('{$descendant_id_csv}')");
                     if (in_array($id, $have_direct_assignments)) {
                         continue;
                     }
                 }
                 if ($eitem_ids = $wpdb->get_col($qry_item_delete_base . " AND exception_id = '{$child_exception_id}' AND item_id = '{$id}'")) {
                     self::remove_exception_items_by_id($eitem_ids);
                 }
                 // note: Propagated roles will be converted to direct-assigned roles if the parent object/term is deleted.
                 //$role_arr['item_id'] = $id;
                 $item_data = array('item_id' => $id, 'assign_for' => 'item', 'exception_id' => $child_exception_id, 'inherited_from' => $this_inherited_from, 'assigner_id' => $assigner_id);
                 $wpdb->insert($wpdb->ppc_exception_items, $item_data);
                 do_action('pp_inserted_exception_item', array_merge((array) $exc, $item_data));
                 //if ( $role_hooks ) {
                 //	$assignment_id = $wpdb->insert_id;
                 //	$role_arr['assign_for'] = 'item';
                 //}
                 $item_data['assign_for'] = 'children';
                 $wpdb->insert($wpdb->ppc_exception_items, $item_data);
                 do_action('pp_inserted_exception_item', array_merge((array) $exc, $item_data));
                 //if ( $role_hooks ) {
                 //	$assignment_id = $wpdb->insert_id;
                 //	$role_arr['assign_for'] = 'children';
                 //}
                 $updated_items[] = $id;
             }
         }
     }
     // end foreach agent_id
     return $updated_items;
 }