diff --git a/css/field_permissions.field.settings.css b/css/field_permissions.field.settings.css
new file mode 100644
index 0000000..a5d7b26
--- /dev/null
+++ b/css/field_permissions.field.settings.css
@@ -0,0 +1,19 @@
+/**
+ * @file
+ * CSS for the permissions matrix on the field settings page.
+ */
+
+/**
+ * Do not display the hide/show descriptions link above the permissions matrix.
+ */
+#field-ui-field-edit-form .compact-link {
+ display: none;
+}
+
+/**
+ * Indent the matrix and make it appear inline with the corresponding radio button.
+ */
+#field-ui-field-edit-form table#permissions {
+ margin-left: 1.5em;
+ width: 98%;
+}
diff --git a/field_permissions.install b/field_permissions.install
index 831c606..5f9b070 100644
--- a/field_permissions.install
+++ b/field_permissions.install
@@ -26,3 +26,101 @@ function field_permissions_update_7000(&$sandbox) {
->execute();
}
+/**
+ * Migrate field permission settings to the new system (public/hidden/custom).
+ */
+function field_permissions_update_7001() {
+ foreach (field_info_fields() as $field_name => $field) {
+ // If the field has any field permissions enabled, it will be using custom
+ // permissions under the new system and needs to be converted. Otherwise,
+ // it is a public field (the default) and can be ignored.
+ if (!empty($field['settings']['field_permissions']) && array_filter($field['settings']['field_permissions'])) {
+ // Set the type to FIELD_PERMISSIONS_CUSTOM. (The module may be disabled
+ // when this update function runs, so we need to use the numeric value
+ // rather than relying on the constant being defined.)
+ $field['field_permissions']['type'] = 2;
+
+ $field_permissions = $field['settings']['field_permissions'];
+ $permissions_by_operation = array(
+ // View-related permissions.
+ array(
+ 'view' => "view $field_name",
+ 'view own' => "view own $field_name",
+ ),
+ // Edit-related permissions.
+ array(
+ 'create' => "create $field_name",
+ 'edit' => "edit $field_name",
+ 'edit own' => "edit own $field_name",
+ ),
+ );
+
+ // Loop through each type of operation (view or edit).
+ foreach ($permissions_by_operation as $permissions) {
+ $actions = array_keys($permissions);
+ // If none of the related permissions were enabled, all users were
+ // allowed to perform the relevant actions on this field, so we need to
+ // assign permissions here to preserve that behavior.
+ $has_enabled_permissions = (bool) array_filter(array_intersect_key($field_permissions, array_flip($actions)));
+ if (!$has_enabled_permissions) {
+ _update_7000_user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, $permissions, 'field_permissions');
+ _update_7000_user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, $permissions, 'field_permissions');
+ }
+ // Otherwise, for each permission that was disabled, no users should be
+ // allowed to perform that action; therefore, make sure to unassign any
+ // (stale) permissions that they may have.
+ else {
+ foreach ($actions as $action) {
+ if (empty($field_permissions[$action])) {
+ if ($action != 'create') {
+ $permission = $permissions[$action];
+ $rids = array_keys(user_roles(FALSE, $permission));
+ foreach ($rids as $rid) {
+ user_role_revoke_permissions($rid, array($permission));
+ }
+ }
+ // The 'create' action needs special handling, since previously,
+ // if create permissions were not enabled the code would have
+ // fallen back on checking edit permissions. Now, though, create
+ // permissions are always enabled (and always checked when an
+ // entity is being created). Therefore, we need to figure out
+ // what the fallback would have been and assign new create
+ // permissions based on that.
+ else {
+ $rids_with_create_access = array();
+ // The first fallback is edit permissions; if those are
+ // enabled, any role with edit permission would have been
+ // granted access.
+ if (!empty($field_permissions['edit'])) {
+ $rids_with_create_access = array_keys(user_roles(FALSE, $permissions['edit']));
+ }
+ // The final fallback is 'edit own' permissions; if those are
+ // enabled, any role with 'edit own' permission would have been
+ // granted access. (It is additionally required that the entity
+ // being checked is owned by the current user, but in the case
+ // of nodes being created that will always be the case anyway,
+ // and nodes are the only entities we need to support for the
+ // D6-to-D7 upgrade.)
+ if (!empty($field_permissions['edit own'])) {
+ $rids_with_create_access = array_unique(array_merge($rids_with_create_access, array_keys(user_roles(FALSE, $permissions['edit own']))));
+ }
+ // Assign create permissions to all the relevant roles.
+ foreach ($rids_with_create_access as $rid) {
+ _update_7000_user_role_grant_permissions($rid, array($permissions['create']), 'field_permissions');
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // Remove the old field permissions settings if necessary, and save the
+ // field.
+ if (isset($field['settings']['field_permissions'])) {
+ // We can't unset this or field_update_field() will automatically add it
+ // back (using the prior field data), so do the next best thing.
+ $field['settings']['field_permissions'] = NULL;
+ field_update_field($field);
+ }
+ }
+}
diff --git a/field_permissions.module b/field_permissions.module
index 0a70d00..6f9cbe2 100644
--- a/field_permissions.module
+++ b/field_permissions.module
@@ -9,6 +9,24 @@
*/
/**
+ * Indicates that a field does not have any access control.
+ */
+define('FIELD_PERMISSIONS_PUBLIC', 0);
+
+/**
+ * Indicates that a field is hidden.
+ *
+ * Hidden fields are never displayed, and are only editable by the author (and
+ * by site administrators with the 'bypass field access' permission).
+ */
+define('FIELD_PERMISSIONS_HIDDEN', 1);
+
+/**
+ * Indicates that a field has custom permissions.
+ */
+define('FIELD_PERMISSIONS_CUSTOM', 2);
+
+/**
* Implements hook_help().
*/
function field_permissions_help($path, $arg) {
@@ -115,21 +133,34 @@ function field_permissions_form_field_ui_field_edit_form_alter(&$form, $form_sta
*/
function field_permissions_field_access($op, $field, $obj_type, $object, $account) {
// Ignore the request if permissions have not been enabled for this field.
- $field_permissions = (isset($field['settings']['field_permissions']) && is_array($field['settings']['field_permissions']) ? array_filter($field['settings']['field_permissions']) : array());
- if (empty($field_permissions)) {
+ if (!isset($field['field_permissions']['type']) || $field['field_permissions']['type'] == FIELD_PERMISSIONS_PUBLIC) {
return;
}
-
- if ($op == 'view') {
- if (!empty($field_permissions['view']) || !empty($field_permissions['view own'])) {
+ // If the field is hidden, then no one is allowed to see it when the object
+ // is being viewed, and only the author (and administrators with the 'bypass
+ // field access' permissions) can edit it.
+ elseif ($field['field_permissions']['type'] == FIELD_PERMISSIONS_HIDDEN) {
+ if ($op == 'view') {
+ return FALSE;
+ }
+ elseif ($op == 'edit') {
module_load_include('inc', 'field_permissions', 'includes/field_access');
- return _field_permissions_field_view_access($field['field_name'], $field_permissions, $obj_type, $object, $account);
+ return _field_permissions_object_is_owned_by_account($object, $account) || user_access('bypass field access', $account);
}
}
- elseif ($op == 'edit') {
- if (!empty($field_permissions['edit']) || !empty($field_permissions['edit own']) || !empty($field_permissions['create'])) {
+ // Otherwise, check access by permission.
+ elseif ($field['field_permissions']['type'] == FIELD_PERMISSIONS_CUSTOM) {
+ if (user_access('bypass field access', $account)) {
+ return TRUE;
+ }
+ else {
module_load_include('inc', 'field_permissions', 'includes/field_access');
- return _field_permissions_field_edit_access($field['field_name'], $field_permissions, $obj_type, $object, $account);
+ if ($op == 'view') {
+ return _field_permissions_field_view_access($field['field_name'], $obj_type, $object, $account);
+ }
+ elseif ($op == 'edit') {
+ return _field_permissions_field_edit_access($field['field_name'], $obj_type, $object, $account);
+ }
}
}
}
diff --git a/includes/admin.inc b/includes/admin.inc
index b79da03..fda7e21 100644
--- a/includes/admin.inc
+++ b/includes/admin.inc
@@ -7,38 +7,90 @@
/**
* Obtain the list of field permissions.
+ *
+ * @param $field_label
+ * The human readable name of the field to use when constructing permission
+ * names. Usually this will be derived from one or more of the field instance
+ * labels.
*/
-function field_permissions_list($field_name = '') {
+function field_permissions_list($field_label = '') {
return array(
'create' => array(
- 'label' => t('Create field'),
- 'title' => t('Create @field', array('@field' => $field_name)),
- 'description' => t('Create @field (edit on content creation).', array('@field' => $field_name)),
- ),
- 'edit' => array(
- 'label' => t('Edit field'),
- 'title' => t('Edit any @field', array('@field' => $field_name)),
- 'description' => t('Edit @field, regardless of content author.', array('@field' => $field_name)),
+ 'label' => t('Add field'),
+ 'title' => t('Add own value for field %field', array('%field' => $field_label)),
),
'edit own' => array(
'label' => t('Edit own field'),
- 'title' => t('Edit own @field', array('@field' => $field_name)),
- 'description' => t('Edit own @field on content created by the user.', array('@field' => $field_name)),
+ 'title' => t('Edit own value for field %field', array('%field' => $field_label)),
),
- 'view' => array(
- 'label' => t('View field'),
- 'title' => t('View any @field', array('@field' => $field_name)),
- 'description' => t('View @field, regardless of content author.', array('@field' => $field_name)),
+ 'edit' => array(
+ 'label' => t('Edit field'),
+ 'title' => t('Edit any value for field %field', array('%field' => $field_label)),
),
'view own' => array(
'label' => t('View own field'),
- 'title' => t('View own @field', array('@field' => $field_name)),
- 'description' => t('View own @field on content created by the user.', array('@field' => $field_name)),
+ 'title' => t('View own value for field %field', array('%field' => $field_label)),
+ ),
+ 'view' => array(
+ 'label' => t('View field'),
+ 'title' => t('View any value for field %field', array('%field' => $field_label)),
),
);
}
/**
+ * Returns field permissions in a format suitable for use in hook_permission().
+ *
+ * @param $field
+ * The field to return permissions for.
+ * @param $label
+ * (optional) The human readable name of the field to use when constructing
+ * permission names; for example, this might be the label of one of the
+ * corresponding field instances. If not provided, an appropriate label will
+ * be automatically derived from all the field's instances.
+ *
+ * @return
+ * An array of permission information, suitable for use in hook_permission().
+ */
+function field_permissions_list_field_permissions($field, $label = NULL) {
+ $description = '';
+
+ // If there is no preferred label, construct one from all the instance
+ // labels.
+ if (!isset($label)) {
+ $labels = array();
+ foreach ($field['bundles'] as $entity_type => $bundles) {
+ foreach ($bundles as $bundle_name) {
+ $instance = field_info_instance($entity_type, $field['field_name'], $bundle_name);
+ $labels[] = $instance['label'];
+ }
+ }
+ // If all the instances have the same label, just use that. Otherwise, use
+ // the field name (with the full list of instance labels as the permission
+ // description).
+ $labels = array_unique($labels);
+ if (count($labels) == 1) {
+ $label = array_shift($labels);
+ }
+ else {
+ $label = $field['field_name'];
+ $description = t('This field appears as: %instances', array('%instances' => implode(', ', $labels)));
+ }
+ }
+
+ $permissions = array();
+ foreach (field_permissions_list($label) as $permission_type => $permission_info) {
+ $permission = $permission_type . ' ' . $field['field_name'];
+ $permissions[$permission] = array(
+ 'title' => $permission_info['title'],
+ 'description' => $description,
+ );
+ }
+
+ return $permissions;
+}
+
+/**
* Implementation of hook_permission().
*/
function _field_permissions_permission() {
@@ -46,20 +98,21 @@ function _field_permissions_permission() {
'administer field permissions' => array(
'title' => t('Administer field permissions'),
'description' => t('Manage field permissions and field permissions settings.'),
+ 'restrict access' => TRUE,
+ ),
+ 'bypass field access' => array(
+ 'title' => t('Bypass field access control'),
+ 'description' => t('Create, edit and view all field values, regardless of permission restrictions.'),
+ 'restrict access' => TRUE,
),
);
- foreach (field_info_fields() as $field_name => $field) {
- if (!empty($field['settings']['field_permissions'])) {
- foreach (field_permissions_list($field_name) as $permission_type => $permission_info) {
- if (!empty($field['settings']['field_permissions'][$permission_type])) {
- $perms[$permission_type . ' ' . $field_name] = array(
- 'title' => $permission_info['title'],
- 'description' => $permission_info['description'],
- );
- }
- }
+
+ foreach (field_info_fields() as $field) {
+ if (isset($field['field_permissions']['type']) && $field['field_permissions']['type'] == FIELD_PERMISSIONS_CUSTOM) {
+ $perms += field_permissions_list_field_permissions($field);
}
}
+
return $perms;
}
@@ -67,50 +120,193 @@ function _field_permissions_permission() {
* Alter the field settings form.
*/
function _field_permissions_field_settings_form_alter(&$form, $form_state, $form_id) {
- // Obtain the field name from the form itself.
- $field_name = isset($form['instance']['field_name']['#value']) ? $form['instance']['field_name']['#value'] : '';
+ // Put the field permissions extensions at the top of the field settings
+ // fieldset.
+ $form['field']['field_permissions'] = array(
+ '#weight' => -10,
+ '#access' => user_access('administer field permissions'),
+ );
- // Try to obtain information about this field.
- $field = field_info_field($field_name);
- if (empty($field)) {
- return;
+ $form['field']['field_permissions']['type'] = array(
+ '#title' => t('Field visibility and permissions'),
+ '#type' => 'radios',
+ '#options' => array(
+ FIELD_PERMISSIONS_PUBLIC => t('Everyone can view'),
+ FIELD_PERMISSIONS_HIDDEN => t('Administrators can view'),
+ FIELD_PERMISSIONS_CUSTOM => t('Custom permissions'),
+ ),
+ '#default_value' => isset($form['#field']['field_permissions']['type']) ? $form['#field']['field_permissions']['type'] : FIELD_PERMISSIONS_PUBLIC,
+ );
+
+ // Add the container in which the field permissions matrix will be displayed.
+ // (and make it so that it is only visible when custom permissions are being
+ // used).
+ $form['field']['field_permissions']['permissions'] = array(
+ '#type' => 'container',
+ '#states' => array(
+ 'visible' => array(
+ // We must cast this to a string until http://drupal.org/node/879580 is
+ // fixed.
+ ':input[name="field[field_permissions][type]"]' => array('value' => (string) FIELD_PERMISSIONS_CUSTOM),
+ ),
+ ),
+ // Custom styling for the permissions matrix on the field settings page.
+ '#attached' => array(
+ 'css' => array(drupal_get_path('module', 'field_permissions') . '/css/field_permissions.field.settings.css'),
+ ),
+ );
+
+ // Add the field permissions matrix itself. Wait until the #pre_render stage
+ // to move it to the above container, to avoid having the permissions data
+ // saved as part of the field record.
+ $form['field_permissions']['#tree'] = TRUE;
+ $form['field_permissions']['permissions'] = field_permissions_permissions_matrix($form['#field'], $form['#instance']);
+ $form['#pre_render'][] = '_field_permissions_field_settings_form_pre_render';
+
+ // Add a submit handler to process the field permissions settings. Note that
+ // it is important for this to run *after* the main field UI submit handler
+ // (which saves the field itself), since when a new field is being created,
+ // our submit handler will try to assign any new custom permissions
+ // immediately, and our hook_permission() implementation relies on the field
+ // info being up-to-date in order for that to work correctly.
+ $form['#submit'][] = '_field_permissions_field_settings_form_submit';
+}
+
+/**
+ * Returns a field permissions matrix that can be inserted into a form.
+ *
+ * The matrix's display is based on that of Drupal's default permissions page.
+ *
+ * Note that this matrix must be accompanied by an appropriate submit handler
+ * (attached to the top level of the form) in order for the permissions in it
+ * to actually be saved. For an example submit handler, see
+ * _field_permissions_field_settings_form_submit().
+ *
+ * @param $field
+ * The field whose permissions will be displayed in the matrix.
+ * @param $instance
+ * The field instance for which the permissions will be displayed. Although
+ * the permissions are per-field rather than per-instance, the instance label
+ * will be used to display an appropriate human-readable name for each
+ * permission.
+ *
+ * @return
+ * A form array defining the permissions matrix.
+ *
+ * @see user_admin_permissions()
+ * @see _field_permissions_field_settings_form_submit()
+ */
+function field_permissions_permissions_matrix($field, $instance) {
+ // This function primarily contains a simplified version of the code from
+ // user_admin_permissions().
+ $form['#theme'] = 'user_admin_permissions';
+ $options = array();
+ $status = array();
+
+ // Retrieve all role names for use in the submit handler.
+ $role_names = user_roles();
+ $form['role_names'] = array(
+ '#type' => 'value',
+ '#value' => $role_names,
+ );
+
+ // Retrieve the permissions for each role, and the field permissions we will
+ // be assigning here.
+ $role_permissions = user_role_permissions($role_names);
+ $field_permissions = field_permissions_list_field_permissions($field, $instance['label']);
+
+ // Determine if it is safe to reset the default values for this field's
+ // permissions. If this is a new field (never saved with field permission
+ // data before), or if it's an existing field that is not currently using
+ // custom permissions and doesn't have any previously-saved ones already in
+ // the database, then it will be safe to reset them.
+ $reset_permissions_defaults = FALSE;
+ if (!isset($field['field_permissions']['type'])) {
+ $reset_permissions_defaults = TRUE;
+ }
+ elseif ($field['field_permissions']['type'] != FIELD_PERMISSIONS_CUSTOM) {
+ $all_assigned_permissions = call_user_func_array('array_merge_recursive', $role_permissions);
+ $assigned_field_permissions = array_intersect_key($all_assigned_permissions, $field_permissions);
+ $reset_permissions_defaults = empty($assigned_field_permissions);
}
- // Enhance the field settings form with field permissions extensions.
- $field_permissions = array();
- foreach (field_permissions_list($field_name) as $permission_type => $permission_info) {
- $field_permissions[$permission_type] = $permission_info['description'];
+ // Go through each field permission we will display.
+ foreach ($field_permissions as $permission => $info) {
+ // Display the name of the permission as a form item.
+ $form['permission'][$permission] = array(
+ '#type' => 'item',
+ '#markup' => $info['title'],
+ );
+ // Save it to be displayed as one of the role checkboxes.
+ $options[$permission] = '';
+ // If we are in a situation where we can reset the field permissions
+ // defaults, we do so by pre-checking the admin role's checkbox for this
+ // permission.
+ if ($reset_permissions_defaults) {
+ if (($admin_rid = variable_get('user_admin_role', 0)) && isset($role_names[$admin_rid])) {
+ $status[$admin_rid][] = $permission;
+ }
+ }
+ // Otherwise (e.g., for fields with custom permissions already saved),
+ // determine whether the permission is already assigned and check each
+ // checkbox accordingly.
+ else {
+ foreach ($role_names as $rid => $name) {
+ if (isset($role_permissions[$rid][$permission])) {
+ $status[$rid][] = $permission;
+ }
+ }
+ }
}
- $form['field']['settings']['field_permissions'] = array(
- '#title' => t('Field permissions'),
- '#type' => 'checkboxes',
- '#checkall' => TRUE,
- '#options' => $field_permissions,
- '#default_value' => (isset($field['settings']['field_permissions']) && is_array($field['settings']['field_permissions']) ? array_filter($field['settings']['field_permissions']) : array()),
- '#description' => t('Use these options to enable role based permissions for this field.
-When permissions are enabled, access to this field is denied by default and explicit permissions should be granted to the proper user roles from the permissions administration page.
-On the other hand, when these options are disabled, field permissions are inherited from the content view and/or edit permissions. In example, users allowed to view a particular node will also be able to view this field, and so on.', array(
- '@admin-permissions' => url('admin/people/permissions', array('fragment' => 'module-field_permissions')),
- )),
- '#weight' => -1,
- );
- // Hide the option to non-privileged users.
- if (!user_access('administer field permissions')) {
- $form['field']['settings']['field_permissions']['#type'] = 'value';
- $form['field']['settings']['field_permissions']['#value'] = $form['field']['settings']['field_permissions']['#default_value'];
+ // Build the checkboxes for each role.
+ foreach ($role_names as $rid => $name) {
+ $form['checkboxes'][$rid] = array(
+ '#type' => 'checkboxes',
+ '#options' => $options,
+ '#default_value' => isset($status[$rid]) ? $status[$rid] : array(),
+ '#attributes' => array('class' => array('rid-' . $rid)),
+ );
+ $form['role_names'][$rid] = array('#markup' => check_plain($name), '#tree' => TRUE);
}
- // Submit handler to grant the new permissions to the administrator role.
- $form['#submit'][] = '_field_permissions_field_settings_form_submit';
+ // Attach the default permissions page JavaScript.
+ $form['#attached']['js'][] = drupal_get_path('module', 'user') . '/user.permissions.js';
+
+ return $form;
+}
+
+/**
+ * Pre-render function for the permissions matrix on the field settings form.
+ */
+function _field_permissions_field_settings_form_pre_render($form) {
+ // Move the permissions matrix to its final location.
+ $form['field']['field_permissions']['permissions']['matrix'] = $form['field_permissions']['permissions'];
+ unset($form['field_permissions']);
+ return $form;
}
/**
* Form callback; Submit handler for the Field Settings form.
*/
-function _field_permissions_field_settings_form_submit() {
- // Grant any new permissions to the admin role.
- user_modules_installed(array('field_permissions'));
+function _field_permissions_field_settings_form_submit($form, &$form_state) {
+ // Save the field permissions when appropriate to do so.
+ $new_field_permissions_type = $form_state['values']['field']['field_permissions']['type'];
+ if ($new_field_permissions_type == FIELD_PERMISSIONS_CUSTOM && isset($form_state['values']['field_permissions']['permissions'])) {
+ $field_permissions = $form_state['values']['field_permissions']['permissions'];
+ foreach ($field_permissions['role_names'] as $rid => $name) {
+ user_role_change_permissions($rid, $field_permissions['checkboxes'][$rid]);
+ }
+ }
+
+ // We must clear the page and block caches whenever the field permission type
+ // setting has changed (because users may now be allowed to see a different
+ // set of fields). For similar reasons, we must clear these caches whenever
+ // custom field permissions are being used, since those may have changed too;
+ // see user_admin_permissions_submit().
+ if (!isset($form['#field']['field_permissions']['type']) || $new_field_permissions_type != $form['#field']['field_permissions']['type'] || $new_field_permissions_type == FIELD_PERMISSIONS_CUSTOM) {
+ cache_clear_all();
+ }
}
/**
@@ -130,6 +326,9 @@ function field_permissions_overview() {
$field_types = field_info_field_types();
$bundles = field_info_bundles();
+ // Retrieve the permissions for each role.
+ $role_permissions = user_role_permissions(user_roles());
+
// Based on field_ui_fields_list() in field_ui.admin.inc.
$rows = array();
foreach ($instances as $obj_type => $type_bundles) {
@@ -143,36 +342,50 @@ function field_permissions_overview() {
$rows[$field_name]['data'][2] = $obj_type;
$rows[$field_name]['data'][3][] = l($bundles[$obj_type][$bundle]['label'], $admin_path . '/fields/'. $field_name, array(
'query' => $destination,
- 'fragment' => 'edit-field-settings-field-permissions',
+ 'fragment' => 'edit-field-field-permissions-type',
));
$rows[$field_name]['class'] = $field['locked'] ? array('menu-disabled') : array('');
// Append field permissions information to the report.
- $field_permissions = (isset($field['settings']['field_permissions']) && is_array($field['settings']['field_permissions']) ? array_filter($field['settings']['field_permissions']) : array());
- foreach (array_keys(field_permissions_list()) as $index => $permission_type) {
+ $type = isset($field['field_permissions']['type']) ? $field['field_permissions']['type'] : FIELD_PERMISSIONS_PUBLIC;
+ foreach (array_keys(field_permissions_list_field_permissions($field)) as $index => $permission) {
// Put together the data value for the cell.
$data = '';
- if (!empty($field_permissions[$permission_type])) {
- // Link the Enabled permission to the permissions page.
+ $full_colspan = FALSE;
+ if ($type == FIELD_PERMISSIONS_PUBLIC) {
+ $data = t('Public field (everyone can access)');
+ $full_colspan = TRUE;
+ }
+ elseif ($type == FIELD_PERMISSIONS_HIDDEN) {
+ $data = t('Hidden field (only the author and administrators can edit)');
+ $full_colspan = TRUE;
+ }
+ else {
+ // This is a field with custom permissions. Link the field to the
+ // appropriate row of the permissions page, and theme it based on
+ // whether all users have access.
+ $all_users_have_access = isset($role_permissions[DRUPAL_ANONYMOUS_RID][$permission]) && isset($role_permissions[DRUPAL_AUTHENTICATED_RID][$permission]);
+ $status_class = $all_users_have_access ? 'field-permissions-status-on' : 'field-permissions-status-off';
+ $title = $all_users_have_access ? t('All users have this permission') : t('Not all users have this permission');
$data = l('', 'admin/people/permissions', array(
'attributes' => array(
- 'class' => array('field-permissions-status', 'field-permissions-status-on'),
- 'title' => t('Enabled'),
+ 'class' => array('field-permissions-status', $status_class),
+ 'title' => $title,
),
- 'fragment' => drupal_html_class("edit $permission_type $field_name"),
+ 'query' => $destination,
+ 'fragment' => drupal_html_class("edit $permission"),
));
}
- else {
- // Simply display the status off text.
- $title = t('Disabled');
- $data = '';
- }
// Construct the cell.
$rows[$field_name]['data'][4 + $index] = array(
'data' => $data,
'class' => array('field-permissions-cell'),
);
+ if ($full_colspan) {
+ $rows[$field_name]['data'][4 + $index]['colspan'] = 5;
+ break;
+ }
}
}
}
diff --git a/includes/field_access.inc b/includes/field_access.inc
index 6d845b7..a09fc4e 100644
--- a/includes/field_access.inc
+++ b/includes/field_access.inc
@@ -8,15 +8,15 @@
/**
* Implementation of hook_field_access('view').
*/
-function _field_permissions_field_view_access($field_name, $field_permissions, $obj_type, $object, $account) {
+function _field_permissions_field_view_access($field_name, $obj_type, $object, $account) {
// Check if user has access to view this field in any object.
- if (!empty($field_permissions['view']) && user_access('view '. $field_name, $account)) {
+ if (user_access('view '. $field_name, $account)) {
return TRUE;
}
- // If 'view own' permission has been enabled for this field, then we can
- // check if the user has the right permission, and ownership of the object.
- if (!empty($field_permissions['view own']) && user_access('view own '. $field_name, $account)) {
+ // If the user has permission to view objects that they own, return TRUE if
+ // they own this object or FALSE if they don't.
+ if (user_access('view own '. $field_name, $account)) {
// When field_access('view') is invoked, it may or may not provide
// an object. It will, almost always, except when this function is
@@ -31,27 +31,7 @@ function _field_permissions_field_view_access($field_name, $field_permissions, $
return TRUE;
}
- // Try to get the uid of the object author from the object itself.
- // When invoked by Views to render a field, we may not have the uid of the
- // object, so we need to retrieve it from the object table.
- if (isset($object->uid)) {
- $object_uid = $object->uid;
- }
- // @todo: what to do with non-node objects?
- elseif (!empty($object->vid)) {
- $object_uid = db_query('SELECT uid FROM {node_revision} WHERE vid = :vid', array(':vid' => $object->vid))->fetchField();
- }
- elseif (!empty($object->nid)) {
- $object_uid = db_query('SELECT uid FROM {node} WHERE nid = :nid', array(':nid' => $object->nid))->fetchField();
- }
- else {
- // Deny access to view the field if we have not been able to get the uid
- // of the object author.
- return FALSE;
- }
-
- // Finally, we can now check if ownership of the object matches.
- return (is_numeric($object_uid) && $object_uid == $account->uid);
+ return _field_permissions_object_is_owned_by_account($object, $account);
}
return FALSE;
@@ -60,22 +40,49 @@ function _field_permissions_field_view_access($field_name, $field_permissions, $
/**
* Implementation of hook_field_access('edit').
*/
-function _field_permissions_field_edit_access($field_name, $field_permissions, $obj_type, $object, $account) {
+function _field_permissions_field_edit_access($field_name, $obj_type, $object, $account) {
// Check if user has access to edit this field on object creation.
- if (empty($object->nid) && !empty($field_permissions['create'])) {
+ if (empty($object->nid)) {
return user_access('create '. $field_name, $account);
}
// Check if user has access to edit this field in any object.
- if (!empty($field_permissions['edit']) && user_access('edit '. $field_name, $account)) {
+ if (user_access('edit '. $field_name, $account)) {
return TRUE;
}
- // If 'edit own' permission has been enabled for this field, then we can
- // check if the user has the right permission, and ownership of the object.
- if (!empty($field_permissions['edit own']) && user_access('edit own '. $field_name, $account) && $object->uid == $account->uid) {
+ // If the user has permission to edit objects that they own, check if they
+ // own this object and return TRUE if they do.
+ if (user_access('edit own '. $field_name, $account) && _field_permissions_object_is_owned_by_account($object, $account)) {
return TRUE;
}
return FALSE;
}
+
+/**
+ * Returns TRUE if an object is owned by a user account, FALSE otherwise.
+ */
+function _field_permissions_object_is_owned_by_account($object, $account) {
+ // Try to get the uid of the object author from the object itself. When
+ // invoked by Views to render a field, we may not have the uid of the object,
+ // so we need to retrieve it from the object table.
+ if (isset($object->uid)) {
+ $object_uid = $object->uid;
+ }
+ // @todo: what to do with non-node objects?
+ elseif (!empty($object->vid)) {
+ $object_uid = db_query('SELECT uid FROM {node_revision} WHERE vid = :vid', array(':vid' => $object->vid))->fetchField();
+ }
+ elseif (!empty($object->nid)) {
+ $object_uid = db_query('SELECT uid FROM {node} WHERE nid = :nid', array(':nid' => $object->nid))->fetchField();
+ }
+ else {
+ // Deny access to view the field if we have not been able to get the uid of
+ // the object author.
+ return FALSE;
+ }
+
+ // Finally, we can now check if ownership of the object matches.
+ return (is_numeric($object_uid) && $object_uid == $account->uid);
+}