diff --git a/includes/og_features_bundle_permissions.features.inc b/includes/og_features_bundle_permissions.features.inc index e69de29..2e0c038 100644 --- a/includes/og_features_bundle_permissions.features.inc +++ b/includes/og_features_bundle_permissions.features.inc @@ -0,0 +1,180 @@ + $bundles) { + foreach($bundles as $bundle => $permissions) { + foreach($permissions as $permission => $info) { + $key = $entity_type . ':' . $bundle . ':' . $permission; + $name = '(' . $entity_type . ':' . $bundle . ') ' . $permission; + $options[$key] = strip_tags($module_info[$info['module']]['name'] . ': ' . $name); + } + } + } + + return $options; +} + +/** + * Helper function to get all roles by group bundle and group type + */ +function _og_features_entity_bundle_permissions() { + $perms = &drupal_static(__FUNCTION__, array()); + + if (empty($perms)) { + $query = db_select('og_role', 'ogr'); + $query->join('og_role_permission', 'orp', 'ogr.rid = orp.rid'); + $result = $query->fields('ogr', array('group_type', 'group_bundle', 'name', 'rid')) + ->fields('orp', array('module', 'permission')) + ->condition('ogr.group_type', '', '!=') + ->condition('ogr.group_bundle', '', '!=') + ->orderBy('ogr.group_type') + ->orderBy('ogr.group_bundle') + ->orderBy('orp.permission') + ->execute(); + + while ($row = $result->fetchAssoc()) { + $perms[$row['group_type']][$row['group_bundle']][$row['permission']]['module'] = $row['module']; + $perms[$row['group_type']][$row['group_bundle']][$row['permission']]['roles'][$row['rid']] = $row['name']; + } + } + return $perms; +} + +/** + * Implements hook_Features_export_render(). + */ +function og_features_bundle_permissions_features_export_render($module, $data) { + $code = array(); + $code[] = ' $permissions = array();'; + $code[] = ''; + + $perms = _og_features_entity_bundle_permissions(); + + foreach($data as $key) { + // $key is 'entity_type:bundle:permission'. + $parts = explode(':', $key); + + // Don't export code if no roles have this permission. + if (!empty($perms[$parts[0]][$parts[1]][$parts[2]]['roles'])) { + $permission = array(); + $roles = $perms[$parts[0]][$parts[1]][$parts[2]]['roles']; + + $permission['roles'] = array_combine($roles, $roles); + + $perm_identifier = features_var_export($key); + $perm_export = features_var_export($permission, ' '); + $code[] = " // Exported og permission: {$perm_identifier}"; + $code[] = " \$permissions[{$perm_identifier}] = {$perm_export};"; + $code[] = ''; + } + } + $code[] = ' return $permissions;'; + + $code = implode("\n", $code); + return array('og_default_bundle_permissions' => $code); +} + +/** + * Implements hook_features_revert(). + */ +function og_features_bundle_permissions_features_revert($module) { + og_features_bundle_permission_features_rebuild($module); +} + +/** + * Implements hook_features_rebuild(). + * Iterates through default permissions and update the permissions map. + * + * @param $module + * The modules whose default user permissions should be rebuild. + */ +function og_features_bundle_permission_features_rebuild($module) { + $roles = _og_features_get_roles(); + if ($defaults = features_get_default('og_features_bundle_permission', $module)) { + $grant = array(); + $revoke = array(); + + foreach($defaults as $key => $details) { + list($entity_type, $bundle, $perm) = explode(':', $key); + + // Make sure the role exists for this entity. + foreach($details['roles'] as $role) { + $bundle_role = _og_features_get_role_by_name($role, $entity_type, $bundle); + if (empty($bundle_role)) { + // See if we can find a global role matching. + $global_role = _og_features_get_role_by_name($role); + if (!empty($global_role)) { + // Create a bundle specific role if there is a corresponding global role + // otherwise we fail on thise role/permission as this is outside scope for + // og_features_bundle_permission + unset($global_role->rid); + $global_role->group_type = $entity_type; + $global_role->group_bundle = $bundle; + og_role_save($global_role); + } + } + } + + $roles = og_roles($entity_type, 0, $bundle); + foreach($roles as $rid => $rolename) { + if (in_array($rolename, $details['roles'])) { + $grant[$rid][] = $perm; + } + else { + $revoke[$rid][] = $perm; + } + } + } + if (!empty($grant)) { + foreach($grant as $rid => $permissions) { + og_role_grant_permissions($rid, $permissions); + } + } + + if (!empty($revoke)) { + foreach($revoke as $rid => $permissions) { + og_role_revoke_permissions($rid, $permissions); + } + } + } +} diff --git a/includes/og_features_permission.features.inc b/includes/og_features_permission.features.inc index e69de29..aa44802 100644 --- a/includes/og_features_permission.features.inc +++ b/includes/og_features_permission.features.inc @@ -0,0 +1,142 @@ + $details) { + $options[$perm] = strip_tags($module_info[$details['module']]['name'] . ': ' . $details['title']); + } + + return $options; +} + +/** + * Implements hook_Features_export_render(). + */ +function og_features_permission_features_export_render($module, $data) { + $code = array(); + $code[] = ' $permissions = array();'; + $code[] = ''; + + $permissions = _og_features_global_permission_permissions_map(); + + foreach($data as $perm_name) { + $permission = array(); + $permission['name'] = $perm_name; + if (isset($permissions[$perm_name])) { + $permission['roles'] = $permissions[$perm_name]['roles']; + $permission['module'] = $permissions[$perm_name]['module']; + } + $perm_identifier = features_var_export($perm_name); + $perm_export = features_var_export($permission, ' '); + $code[] = " // Exported og permission: {$perm_name}"; + $code[] = " \$permissions[{$perm_identifier}] = {$perm_export};"; + $code[] = ''; + } + $code[] = ' return $permissions;'; + + $code = implode("\n", $code); + return (array('og_default_permissions' => $code)); +} + +/** + * Implements hook_features_revert(). + */ +function og_features_permission_features_revert($module) { + og_features_permission_features_rebuild($module); +} + +/** + * Implements hook_features_rebuild(). + * Iterates through default permissions and update the permissions map. + * + * @param $module + * The modules whose default user permissions should be rebuild. + */ +function og_features_permission_features_rebuild($module) { + $roles = _og_features_get_roles(); + $rmap = array_flip($roles); + if ($defaults = features_get_default('og_features_permission', $module)) { + $grant = array(); + $revoke = array(); + foreach($defaults as $perm => $details) { + foreach ($roles as $rolename) { + if (!empty($rmap[$rolename])) { + if (in_array($rolename, $details['roles'])) { + $grant[$rmap[$rolename]][] = $perm; + } + else { + $revoke[$rmap[$rolename]][] = $perm; + } + } + } + } + + if (!empty($grant)) { + foreach($grant as $rid => $permissions) { + og_role_grant_permissions($rid, $permissions); + } + } + + if (!empty($revoke)) { + foreach($revoke as $rid => $permissions) { + og_role_revoke_permissions($rid, $permissions); + } + } + } +} + +/** + * Helper function to flip role/perm map + */ +function _og_features_global_permission_permissions_map() { + $perms = og_get_default_permissions(); + $roles = _og_features_get_roles(); + $permissions = og_get_permissions(); + $map = array(); + foreach($permissions as $perm => $details) { + $map[$perm] = array( + 'module' => $details['module'], + 'roles' => array(), + ); + foreach($perms as $rid => $rperms) { + if (!empty($rperms[$perm])) { + $map[$perm]['roles'][] = $roles[$rid]; + } + } + + sort($map[$perm]['roles']); + } + + return $map; +} diff --git a/includes/og_features_role.features.inc b/includes/og_features_role.features.inc index e69de29..5348a38 100644 --- a/includes/og_features_role.features.inc +++ b/includes/og_features_role.features.inc @@ -0,0 +1,71 @@ +rid); + $role_identifier = features_var_export($name); + $role_export = features_var_export($role, ' '); + $code[] = " // Exported role: {$name}"; + $code[] = " \$roles[{$role_identifier}] = {$role_export};"; + $code[] = ""; + } + } + + $code[] = ' return $roles;'; + $code = implode("\n", $code); + return array('og_default_roles' => $code); +} + +/** + * Implements hook_features_revert + */ +function og_features_role_features_revert($module) { + og_features_role_features_rebuild($module); +} + +/** + * Implements hook_features_rebuild() + */ +function og_features_role_features_rebuild($module) { + if ($defaults = features_get_default('og_features_role', $module)) { + foreach($defaults as $role) { + $role = (object) $role; + if ($existing = _og_features_get_role_by_name($role->name)) { + $role->rid = $existing->rid; + } + og_role_save($role); + } + } +} diff --git a/og.module b/og.module index 9615a8d..deb1b4b 100644 --- a/og.module +++ b/og.module @@ -3310,3 +3310,69 @@ function og_operations_load_action_includes() { return $files; } + +/** + * Implements hook_features_api(). + */ +function og_features_api() { + return array( + 'og_features_role' => array( + 'name' => t('OG Role'), + 'feature source' => TRUE, + 'default_hook' => 'og_default_roles', + 'default_file' => FEATURES_DEFAULTS_INCLUDED, + 'file' => drupal_get_path('module', 'og') .'/includes/og_features_role.features.inc', + ), + 'og_features_permission' => array( + 'name' => t('OG Permissions'), + 'feature_source' => TRUE, + 'default_hook' => 'og_default_permissions', + 'default_file' => FEATURES_DEFAULTS_INCLUDED, + 'file' => drupal_get_path('module', 'og') .'/includes/og_features_permission.features.inc', + ), + 'og_features_bundle_permissions' => array( + 'name' => t('OG Bundle Permissions'), + 'feature_source' => TRUE, + 'default_hook' => 'og_default_bundle_permissions', + 'default_file' => FEATURES_DEFAULTS_INCLUDED, + 'file' => drupal_get_path('module', 'og') .'/includes/og_features_bundle_permissions.features.inc', + ), + ); +} + +/** + * Get a user role by name + */ +function _og_features_get_role_by_name($name, $group_type = '', $bundle = '') { + return db_select('og_role', 'r') + ->fields('r') + ->condition('name', $name) + ->condition('gid', 0) + ->condition('group_type', $group_type) + ->condition('group_bundle', $bundle) + ->execute() + ->fetchObject(); +} + +/** + * Generate $rid => $role with role names untranslated + */ +function _og_features_get_roles($builtin = TRUE) { + $roles = array(); + foreach(og_get_default_roles() as $rid => $name) { + switch ($name) { + case OG_ANONYMOUS_ROLE: + case OG_AUTHENTICATED_ROLE: + case OG_ADMINISTRATOR_ROLE: + if ($builtin) { + $roles[$rid] = $name; + } + break; + default: + $roles[$rid] = $name; + break; + } + } + return $roles; +} +