locked ) {
$notice = sprintf('A plugin or theme (%1$s) is too late in its attempt to define a capability (%2$s).', $defining_module, $name)
. '
' . 'This must be done via the define_capabilities_rs hook.';
rs_notice($notice);
return;
}
if ( isset($this->members[$name]) )
unset($this->members[$name]);
$this->members[$name] = new CR_Capability($name, $defining_module, $src_name, $object_type, $op_type, $args);
$this->process($this->members[$name]);
return $this->members[$name];
}
function process( &$cap_def ) {
if ( ! isset($cap_def->status) )
$cap_def->status = '';
}
// legacy API
function object_types_from_caps($reqd_caps) {
if ( ! is_array($reqd_caps) )
$reqd_caps = ($reqd_caps) ? array($reqd_caps) : array();
$object_types = array();
foreach( $reqd_caps as $cap_name) {
if ( isset($this->members[$cap_name]) ) {
$cap_def = $this->members[$cap_name];
if ( isset($cap_def->src_name) && isset($cap_def->object_type) )
$object_types[$cap_def->src_name][$cap_def->object_type] = 1;
}
}
return $object_types;
}
//returns array[src_name][object_type] = 1
function src_otypes_from_caps( $reqd_caps, &$src_name ) {
if ( ! is_array($reqd_caps) )
$reqd_caps = ($reqd_caps) ? array($reqd_caps) : array();
$object_types = array();
foreach( $reqd_caps as $cap_name)
if ( $cap_def = $this->get($cap_name) )
if ( ! empty($cap_def->src_name) && ! empty($cap_def->object_types) ) {
foreach( $cap_def->object_types as $type )
$object_types[$cap_def->src_name] [] = $type;
}
// If multiple sources were identified from these caps, the reqd_caps set is at least partially invalid.
// If post data source was among those identified, return its post types. Otherwise, fail.
if ( count( $object_types ) > 1 ) {
if ( isset( $object_types['post'] ) )
$object_types = array_intersect( $object_types, array( 'post' ) );
else {
$src_name = '';
return array();
}
}
reset($object_types);
$src_name = key($object_types);
if ( isset( $object_types[$src_name] ) )
return $object_types[$src_name];
else
return array();
}
function get_cap_ops($caps, $src_name = '', $object_type = '') {
$ops = array();
foreach ( $caps as $cap_name )
if ( ! empty($this->members[$cap_name]->op_type) )
$ops[ $this->members[$cap_name]->op_type ] = 1;
return $ops;
}
// returns caps array[op_type] = array of cap names
function organize_caps_by_op($caps, $include_undefined_caps = false ) {
$opcaps = array();
foreach ($caps as $cap_name) {
if ( isset($this->members[$cap_name]) ) {
$op_type = ( isset( $this->members[$cap_name]->op_type ) ) ? $this->members[$cap_name]->op_type : '';
$opcaps[$op_type] []= $cap_name;
} elseif ( $include_undefined_caps )
$opcaps[''] []= $cap_name;
}
return $opcaps;
}
// returns caps array[src_name][object_type] = array of cap names
function organize_caps_by_otype( $caps, $include_undefined_caps = false, $required_src_name = '', $default_object_type = '' ) {
$otype_caps = array();
foreach ($caps as $cap_name) {
if ( isset($this->members[$cap_name]) ) {
$src_name = $this->members[$cap_name]->src_name;
if ( $required_src_name && ( $src_name != $required_src_name ) ) {
$src_name = '';
$otype_caps[''][''] []= $cap_name;
} else {
if ( ! empty($this->members[$cap_name]->object_types) ) {
foreach( $this->members[$cap_name]->object_types as $_object_type ) {
$otype_caps[$src_name][$_object_type] []= $cap_name;
}
} else {
$otype_caps[$src_name][$default_object_type] []= $cap_name;
}
}
} elseif ( $include_undefined_caps )
$otype_caps[''][''] []= $cap_name;
}
// TODO: is this still necessary?
// if an otype-indeterminate cap is present alongside otype-specific caps, combine them into the otype-specfic array(s)
foreach ( array_keys($otype_caps) as $src_name ) {
if ( (count($otype_caps[$src_name]) > 1) && isset($otype_caps[$src_name]['']) ) {
foreach ( array_keys($otype_caps[$src_name]) as $otype ) {
if ( $otype )
$otype_caps[$src_name][$otype] = array_merge($otype_caps[$src_name][$otype], $otype_caps[$src_name][''] );
}
unset ($otype_caps[$src_name]['']);
}
}
return $otype_caps;
}
// Remove "others" caps from array
// If $substitute is set true, replace with corresponding base cap
function get_base_caps($caps, $substitute = true ) {
$caps = (array) $caps;
foreach ( $caps as $key => $cap_name )
if ( ! empty($this->members[$cap_name]->base_cap) ) {
if ( $substitute )
$caps[$key] = $this->members[$cap_name]->base_cap;
else
unset( $caps[$key] );
}
return array_unique($caps);
}
// Remove "others" caps from array
function remove_owner_caps($caps) {
return $this->get_base_caps($caps, false);
}
function get_matching($src_name, $object_types = '', $op_type = '', $status = '', $base_caps_only = false, $args = array() ) {
$arr = array();
$defaults = array( 'strict_op_match' => false, 'strict_otype_match' => false);
$args = array_intersect_key( array_merge( $defaults, (array) $args ), $defaults );
extract($args);
$object_types = ( $object_types ) ? (array) $object_types : array();
// disregard a status arg which is not present in any cap
if ( $status && ( $status != STATUS_ANY_RS ) ) {
$status_present = false;
foreach ( $this->members as $cap_name => $capdef )
if ( isset($capdef->status) && ( $capdef->status == $status ) ) {
$status_present = true;
break;
}
if ( ! $status_present )
$status = '';
}
// first narrow to specified source name, object type, status and baseness
foreach ( $this->members as $cap_name => $capdef ) {
if ( ( isset($capdef->src_name) && $capdef->src_name == $src_name )
&& ( empty($object_types) || ( isset($capdef->object_types) && array_intersect( $object_types, $capdef->object_types ) ) || ( empty($strict_otype_match) && empty($capdef->object_types) ) )
&& ( (STATUS_ANY_RS == $status) || ( ! $status && empty($capdef->status) ) || ( isset($capdef->status) && ($status == $capdef->status) ) )
&& ( ! $base_caps_only || empty($capdef->base_cap) )
)
$arr[$cap_name] = $capdef;
}
// Narrow to specified op type.
// But if no cap of this op type is defined, sustitute a cap of higher op level (which also met the other criteria)
if ( $arr && $op_type ) {
$sustitute_ops = array( OP_EDIT_RS, OP_PUBLISH_RS, OP_DELETE_RS, OP_ADMIN_RS );
if ( ! $op_level = array_search($op_type, $sustitute_ops) )
$op_level = -1;
$op_caps = array();
do {
if ( $op_level >= 0 )
$op_type = $sustitute_ops[$op_level];
foreach ( $arr as $cap_name => $capdef )
if ( $capdef->op_type == $op_type )
$op_caps[$cap_name] = $capdef;
$op_level++;
} while ( ! $op_caps && ($op_level < count($sustitute_ops) ) && empty($strict_op_match) );
return $op_caps;
} else
return $arr;
}
}
class CR_Capability extends AGP_Config_Item {
var $src_name; // required
var $object_types = array(); // array[object_type] = true : populated based on cap usage in RS roles
var $op_type; // required
var $status = '';
var $base_cap; // documentation not finished - see scoper_core_cap_defs()
var $anon_user_has; // ''
var $is_taxonomy_cap; // ''
// args: status, base_cap, anon_user_has, is_taxonomy_cap
function CR_Capability($name, $defining_module, $src_name, $object_type = '', $op_type = '', $args) {
$this->AGP_Config_Item($name, $defining_module, $args);
$this->src_name = $src_name;
if ( $object_type )
$this->object_types[] = $object_type;
$this->op_type = $op_type;
}
}
?>