PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/role-scoper/roles_rs.php

https://bitbucket.org/broderboy/nycendurance-wordpress
PHP | 406 lines | 283 code | 92 blank | 31 comment | 89 complexity | a3bf984c84d692b45fd71cff6804ed99 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-3.0, Apache-2.0, GPL-2.0, LGPL-2.1
  1. <?php
  2. if( basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']) )
  3. die();
  4. require_once( dirname(__FILE__).'/lib/agapetry_config_items.php');
  5. class CR_Roles extends AGP_Config_Items {
  6. var $role_caps = array();
  7. var $role_types = array();
  8. var $display_names = array(); // display_names, abbrevs necessary for WP roles (supported for use by RS Extensions, but default role defs call ScoperRoleStrings functions instead
  9. var $abbrevs = array();
  10. var $micro_abbrevs = array();
  11. function CR_Roles( $arr = '', $action_hook = '') {
  12. $this->role_types = array( 'rs', 'wp' );
  13. $this->AGP_Config_Items( $arr, $action_hook );
  14. }
  15. function get_display_name( $role_handle, $context = '' ) {
  16. if ( isset( $this->display_names[$role_handle] ) )
  17. return $this->display_names[$role_handle];
  18. require_once( dirname(__FILE__).'/roles-strings_rs.php' );
  19. return ScoperRoleStrings::get_display_name( $role_handle, $context );
  20. }
  21. function get_abbrev( $role_handle, $context = '' ) {
  22. if ( isset( $this->abbrevs[$role_handle] ) )
  23. return $this->abbrevs[$role_handle];
  24. require_once( dirname(__FILE__).'/roles-strings_rs.php' );
  25. return ScoperRoleStrings::get_abbrev( $role_handle, $context );
  26. }
  27. function get_micro_abbrev( $role_handle, $context = '' ) {
  28. if ( isset( $this->micro_abbrevs[$role_handle] ) )
  29. return $this->micro_abbrevs[$role_handle];
  30. require_once( dirname(__FILE__).'/roles-strings_rs.php' );
  31. if( ! $return = ScoperRoleStrings::get_micro_abbrev( $role_handle, $context ) )
  32. $return = ScoperRoleStrings::get_abbrev( $role_handle, $context );
  33. return $return;
  34. }
  35. function &add($name, $defining_module, $display_name = '', $abbrev = '', $role_type = 'rs', $args = array()) {
  36. if ( $this->locked ) {
  37. $notice = sprintf('A plugin or theme (%1$s) is too late in its attempt to define a role (%2$s).', $defining_module, $name)
  38. . '<br /><br />' . 'This must be done via the define_roles_rs hook.';
  39. rs_notice($notice);
  40. return;
  41. }
  42. $key = ( $name == ANON_ROLEHANDLE_RS ) ? $name : scoper_get_role_handle($name, $role_type);
  43. if ( 'wp' == $role_type ) {
  44. if ( ! $display_name )
  45. $display_name = ucwords( str_replace('_', ' ', $name) );
  46. if ( ! $abbrev )
  47. $abbrev = $display_name;
  48. }
  49. if ( $display_name )
  50. $this->display_names[$key] = $display_name;
  51. if ( $abbrev )
  52. $this->abbrevs[$key] = $abbrev;
  53. if ( isset($this->members[$key]) )
  54. unset($this->members[$key]);
  55. $this->members[$key] = new CR_Role($name, $defining_module, $role_type, $args);
  56. $this->process($this->members[$key]);
  57. return $this->members[$key];
  58. }
  59. function process( &$role_def ) {
  60. // role type was prefixed for array key, but should remove for name property
  61. foreach ( $this->role_types as $role_type ) {
  62. $role_def->name = str_replace("{$role_type}_", '', $role_def->name);
  63. }
  64. if ( ! isset($role_def->valid_scopes) )
  65. $role_def->valid_scopes = array('blog' => 1, 'term' => 1, 'object' => 1);
  66. if ( ! isset($role_def->src_name) )
  67. $role_def->src_name = '';
  68. if ( ! isset($role_def->object_type) )
  69. $role_def->object_type = ( 'rs' == $role_def->role_type ) ? $role_def->src_name : '';
  70. }
  71. function add_role_caps( $user_role_caps ) {
  72. if ( ! is_array( $user_role_caps ) )
  73. return;
  74. foreach( array_keys( $user_role_caps ) as $role_handle ) {
  75. if ( $user_role_caps[$role_handle] ) {
  76. if( isset( $this->role_caps[$role_handle] ) )
  77. $this->role_caps[$role_handle] = array_merge($this->role_caps[$role_handle], $user_role_caps[$role_handle]);
  78. else
  79. $this->role_caps[$role_handle] = $user_role_caps[$role_handle];
  80. }
  81. }
  82. }
  83. function remove_role_caps( $disabled_role_caps ) {
  84. if ( ! is_array( $disabled_role_caps ) )
  85. return;
  86. foreach ( array_keys($this->role_caps) as $role_handle )
  87. if ( ! empty($disabled_role_caps[$role_handle]) )
  88. $this->role_caps[$role_handle] = array_diff_key($this->role_caps[$role_handle], $disabled_role_caps[$role_handle]);
  89. }
  90. function get_for_taxonomy($src, $taxonomy = '', $args = array()) {
  91. $defaults = array( 'one_otype_per_role' => true, 'ignore_usage_settings' => false );
  92. $args = array_merge( $defaults, (array) $args );
  93. extract($args);
  94. if ( ! is_object($src) )
  95. $src = $GLOBALS['scoper']->data_sources->get($src);
  96. if ( ! $src)
  97. return;
  98. $otype_roles = array();
  99. if ( ! in_array( $taxonomy, array( 'category', 'post_tag' ) ) && $one_otype_per_role ) {
  100. if ( $tx = get_taxonomy( $taxonomy ) )
  101. if ( ! empty( $tx->object_type ) )
  102. $use_otypes = array_unique( (array) $tx->object_type );
  103. }
  104. if ( empty( $use_otypes ) )
  105. $use_otypes = array_keys($src->object_types);
  106. foreach ( $use_otypes as $object_type ) {
  107. $use_term_roles = scoper_get_otype_option('use_term_roles', $src->name, $object_type);
  108. if ( ! $ignore_usage_settings && empty($use_term_roles[$taxonomy]) )
  109. continue;
  110. if ( $roles = $this->get_matching( 'rs', $src->name, $object_type ) ) {
  111. if ( $one_otype_per_role )
  112. foreach ( array_keys($otype_roles) as $existing_object_type )
  113. $roles = array_diff_key($roles, $otype_roles[$existing_object_type]);
  114. $otype_roles[$object_type] = $roles;
  115. }
  116. }
  117. //note: term roles are defined with src_name property corresponding to their object source (i.e. manage_categories has src_name 'post')
  118. if ( $taxonomy ) {
  119. if ( $roles = $this->get_matching( 'rs', $src->name, $taxonomy ) ) {
  120. if ( $one_otype_per_role )
  121. foreach ( array_keys($otype_roles) as $object_type )
  122. $roles = array_diff_key($roles, $otype_roles[$object_type]);
  123. if ( $roles )
  124. $otype_roles[$taxonomy] = $roles;
  125. }
  126. }
  127. return $otype_roles;
  128. }
  129. function add_containing_roles($roles, $role_type = '') {
  130. $return_roles = $roles;
  131. foreach ( array_keys($roles) as $role_handle )
  132. if ( $containing = $this->get_containing_roles($role_handle, $role_type) )
  133. $return_roles = array_merge($return_roles, $containing);
  134. return $return_roles;
  135. }
  136. // returns array with role handles as keys
  137. function get_containing_roles($role_handle, $role_type = '') {
  138. if ( ! isset($this->role_caps[$role_handle]) || ! is_array($this->role_caps[$role_handle]) )
  139. return array();
  140. $containing_roles = array();
  141. foreach ( array_keys($this->role_caps) as $other_role_handle )
  142. if ( $other_role_handle != $role_handle )
  143. if ( ! array_diff_key($this->role_caps[$role_handle], $this->role_caps[$other_role_handle]) )
  144. $containing_roles[$other_role_handle] = 1;
  145. if ( $containing_roles && $role_type )
  146. $containing_roles = $this->filter_keys( array_keys($containing_roles), array( 'role_type' => $role_type ), 'names_as_key' );
  147. return $containing_roles;
  148. }
  149. // returns array with role handles as key
  150. function get_contained_roles($role_handles, $include_this_role = false, $role_type = '') {
  151. if ( ! $role_handles )
  152. return array();
  153. $role_handles = (array) $role_handles;
  154. $contained_roles = array();
  155. foreach ( $role_handles as $role_handle ) {
  156. if ( ! isset($this->role_caps[$role_handle]) )
  157. continue;
  158. $role_attributes = $this->get_role_attributes( $role_handle );
  159. foreach ( array_keys($this->role_caps) as $other_role_handle ) {
  160. if ( ( ($other_role_handle != $role_handle) || $include_this_role ) ) {
  161. if ( $this->role_caps[$other_role_handle] ) { // don't take credit for including roles that have no pertinent caps
  162. if ( ! array_diff_key($this->role_caps[$other_role_handle], $this->role_caps[$role_handle]) ) {
  163. // role caps qualify, but only count RS roles of matching object type
  164. if ( 'rs' == $role_attributes->role_type ) {
  165. if ( $role_attributes->object_type != $this->member_property( $other_role_handle, 'object_type' ) )
  166. continue;
  167. }
  168. $contained_roles[$other_role_handle] = 1;
  169. }
  170. }
  171. }
  172. }
  173. }
  174. if ( $role_type && $contained_roles )
  175. $contained_roles = $this->filter_keys( array_keys($contained_roles), array( 'role_type' => $role_type ), 'names_as_key' );
  176. if ( $contained_roles && ! $include_this_role )
  177. $contained_roles = array_diff_key( $contained_roles, array_flip($role_handles) );
  178. return $contained_roles;
  179. }
  180. // returns array of role objects
  181. function add_contained_roles($assigned) {
  182. if ( empty($assigned) )
  183. return array();
  184. $assigned = (array) $assigned;
  185. $roles = $assigned;
  186. foreach ( array_keys($assigned) as $assigned_role_handle ) {
  187. if ( $contained_roles = $this->get_contained_roles($assigned_role_handle) )
  188. $roles = array_merge( $roles, $contained_roles );
  189. }
  190. return $roles;
  191. }
  192. // returns array[role_handle] = array of term ids
  193. function add_contained_term_roles($assigned) {
  194. if ( empty($assigned) )
  195. return array();
  196. $assigned = (array) $assigned;
  197. $role_terms = $assigned;
  198. // $assigned[role_key] = array of terms for which the role is assigned.
  199. // Add contained roles directly into the provided assigned_roles array
  200. foreach ( $assigned as $assigned_role_handle => $terms ) {
  201. // if a user has role assigned for term(s), he also effectively has all its contained roles assigned for same term(s)
  202. foreach ( array_keys( $this->get_contained_roles($assigned_role_handle, true) ) as $contained_role_handle ) {
  203. // may or may not already have roles assigned explicitly or via containment in another assigned role
  204. if ( ! isset($role_terms[$contained_role_handle]) )
  205. $role_terms[$contained_role_handle] = $terms;
  206. else
  207. $role_terms[$contained_role_handle] = array_unique( array_merge($role_terms[$contained_role_handle], $terms) );
  208. }
  209. }
  210. return $role_terms;
  211. }
  212. // reqd_caps: array of cap names and/or role handles. Role handle format is {$role_type}_{role_name}
  213. function role_handles_to_caps($reqd_caps, $find_unprefixed_wproles = false) {
  214. foreach ( $reqd_caps as $role_handle ) {
  215. if ( isset($this->role_caps[$role_handle]) ) {
  216. $reqd_caps = array_merge( $reqd_caps, array_keys($this->role_caps[$role_handle]) );
  217. $reqd_caps = array_diff( $reqd_caps, array($role_handle) );
  218. }
  219. }
  220. if ( $find_unprefixed_wproles ) {
  221. global $wp_roles;
  222. foreach ( $reqd_caps as $role_name ) {
  223. if ( isset($wp_roles->role_objects[$role_name]->capabilities ) ) {
  224. $reqd_caps = array_merge( $reqd_caps, array_keys($wp_roles->role_objects[$role_name]->capabilities) );
  225. $reqd_caps = array_diff( $reqd_caps, array($role_name) );
  226. }
  227. }
  228. }
  229. return array_unique($reqd_caps);
  230. }
  231. function get_role_attributes( $role_handle ) {
  232. $attribs = (object) array( 'role_type' => '', 'src_name' => '', 'object_type' => '' );
  233. if ( isset( $this->members[$role_handle] ) ) {
  234. $attribs->role_type = $this->members[$role_handle]->role_type;
  235. if ( 'rs' == $attribs->role_type ) {
  236. $attribs->src_name = $this->members[$role_handle]->src_name;
  237. $attribs->object_type = $this->members[$role_handle]->object_type;
  238. }
  239. }
  240. return $attribs;
  241. }
  242. // returns array of Role_Defs objects which match the specified parameters
  243. function get_matching($role_types = '', $src_names = '', $object_types = '' ) {
  244. if ( $role_handles = $this->qualify_roles( '', $role_types, $object_types, array( 'src_name' => $src_names ) ) )
  245. return array_intersect_key( $this->members, $role_handles );
  246. else
  247. return array();
  248. }
  249. // $reqd_caps = single cap name string OR array of cap name strings
  250. // returns array of role_handles
  251. function qualify_roles($reqd_caps, $role_type = 'rs', $object_type = '', $args = array()) {
  252. $defaults = array( 'src_name' => '', 'all_wp_caps' => false );
  253. $args = array_merge( $defaults, (array) $args );
  254. extract($args);
  255. $good_roles = array();
  256. if ( $reqd_caps )
  257. $reqd_caps = $this->role_handles_to_caps( (array) $reqd_caps, true); // arg: also check for unprefixed WP rolenames
  258. if ( $role_type )
  259. $role_handles = $this->filter_keys( array_keys($this->members), array( 'role_type' => $role_type ) );
  260. else
  261. $role_handles = array_keys($this->members);
  262. foreach ( $role_handles as $role_handle ) {
  263. if ( $reqd_caps ) {
  264. if ( $all_wp_caps && ( 0 === strpos( $role_handle, 'wp_' ) ) ) {
  265. if ( empty( $GLOBALS['wp_roles']->role_objects[ substr($role_handle, 3) ]->capabilities )
  266. || array_diff( $reqd_caps, array_keys( $GLOBALS['wp_roles']->role_objects[ substr($role_handle, 3) ]->capabilities ) ) ) // note: this does not observe "false" value in capabilities array
  267. continue;
  268. } else {
  269. if ( empty( $this->role_caps[$role_handle] ) || array_diff( $reqd_caps, array_keys( $this->role_caps[$role_handle] ) ) )
  270. continue;
  271. }
  272. }
  273. // The required caps test passed or was not applied. Now verify data source and/or object type, if specified...
  274. if ( 'rs' == $this->members[$role_handle]->role_type ) {
  275. // data source and object type matching only apply to RS roles, which always have a single data source and object type defined
  276. if ( $src_name && ! in_array( $this->members[$role_handle]->src_name, (array) $src_name ) )
  277. continue;
  278. // the role qualifies unless its object type is a mismatch
  279. if ( $object_type && ! in_array( $this->members[$role_handle]->object_type, (array) $object_type ) )
  280. continue;
  281. }
  282. $good_roles[$role_handle] = 1;
  283. }
  284. return $good_roles;
  285. }
  286. // Currently, new custom-defined post, page or link roles are problematic because objects or categories with all roles restricted
  287. // will suddenly be non-restricted to users whose WP role contains the newly defined RS role.
  288. //
  289. // TODO: make all custom-defined roles default restricted
  290. function remove_invalid() {
  291. return;
  292. /*
  293. if ( $custom_members = array_diff_key( $this->members, array_fill_keys( array( 'rs_post_reader', 'rs_private_post_reader', 'rs_post_contributor', 'rs_post_author', 'rs_post_revisor', 'rs_post_editor', 'rs_page_reader', 'rs_private_page_reader', 'rs_page_contributor', 'rs_page_author', 'rs_page_revisor', 'rs_page_editor', 'rs_page_associate', 'rs_link_editor', 'rs_category_manager', 'rs_group_manager' ), true ) ) ) {
  294. foreach ( $custom_members as $role_handle => $role_def ) {
  295. if ( ( 'post' == $role_def->src_name ) && in_array( $role_def->object_type, array( 'post', 'page' ) )
  296. || ( ( 'link' == $role_def->src_name ) && ( 'link' == $role_def->object_type ) ) )
  297. unset( $this->members[$role_handle] );
  298. }
  299. }
  300. */
  301. }
  302. } // end class CR_Roles
  303. class CR_Role extends AGP_Config_Item {
  304. var $role_type;
  305. var $src_name;
  306. var $object_type;
  307. var $valid_scopes;
  308. var $objscope_equivalents;
  309. function CR_Role($name, $defining_module, $role_type = 'rs', $args = array() ) {
  310. $this->AGP_Config_Item($name, $defining_module, $args);
  311. $this->role_type = $role_type;
  312. }
  313. }
  314. ?>