Skip to content
Snippets Groups Projects
Commit d7589f2e authored by Claudiu Cristea's avatar Claudiu Cristea Committed by Jakob P
Browse files

Issue #3228881 by japerry: Allow plugins to opt-out for a given field

parent f2b6c78f
No related branches found
No related tags found
1 merge request!5Resolve #3228881 "Allow plugins to opt-out for a given field"
......@@ -95,12 +95,18 @@ function field_permissions_form_field_config_edit_form_alter(&$form, FormStateIn
'#description' => t('Field inherits content permissions.'),
],
];
$definitions = \Drupal::service('plugin.field_permissions.types.manager')->getDefinitions();
foreach ($definitions as $id => $plugin) {
$options[$id] = $plugin['title'];
$descriptions[$id] = [
'#description' => $plugin['description'],
];
$plugin_manager = \Drupal::service('plugin.field_permissions.types.manager');
$definitions = $plugin_manager->getDefinitions();
/** @var \Drupal\field_permissions\Plugin\FieldPermissionTypeInterface[] $plugins */
$plugins = [];
foreach ($definitions as $id => $definition) {
$plugin = $plugin_manager->createInstance($id, [], $field->getFieldStorageDefinition());
if ($plugin->appliesToField($field)) {
$options[$id] = $definition['title'];
$descriptions[$id] = ['#description' => $definition['description']];
$plugins[$id] = $plugin;
}
}
$form['field']['field_permissions']['type'] = [
......@@ -117,11 +123,11 @@ function field_permissions_form_field_config_edit_form_alter(&$form, FormStateIn
$form['actions']['submit']['#submit'][] = 'field_permission_field_config_edit_form_submit';
$form['#entity_builders'][] = 'field_permissions_field_config_edit_form_builder';
$user_role_storage = \Drupal::service('entity_type.manager')->getStorage('user_role');
// Allow each plugin to add to or alter the form.
foreach ($definitions as $definition) {
$plugin = \Drupal::service('plugin.field_permissions.types.manager')->createInstance($definition['id'], [], $field->getFieldStorageDefinition());
foreach ($plugins as $plugin) {
if ($plugin instanceof AdminFormSettingsInterface) {
$plugin->buildAdminForm($form, $form_state, \Drupal::service('entity_type.manager')->getStorage('user_role'));
$plugin->buildAdminForm($form, $form_state, $user_role_storage);
}
}
}
......
......@@ -171,7 +171,7 @@ class FieldPermissionsService implements FieldPermissionsServiceInterface, Conta
// Pass access control to the plugin.
$plugin = $this->permissionTypeManager->createInstance($permission_type, [], $field_definition->getFieldStorageDefinition());
return $plugin->hasFieldAccess($operation, $items->getEntity(), $account);
return $plugin->appliesToField($field_definition) && $plugin->hasFieldAccess($operation, $items->getEntity(), $account);
}
/**
......@@ -207,7 +207,7 @@ class FieldPermissionsService implements FieldPermissionsServiceInterface, Conta
// Pass access control to the plugin.
$plugin = $this->permissionTypeManager->createInstance($permission_type, [], $field_definition->getFieldStorageDefinition());
if ($plugin instanceof Base) {
return $plugin->hasFieldViewAccessForEveryEntity($account);
return $plugin->appliesToField($field_definition) && $plugin->hasFieldViewAccessForEveryEntity($account);
}
else {
return FALSE;
......
......@@ -2,6 +2,7 @@
namespace Drupal\field_permissions\Plugin\FieldPermissionType;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Session\AccountInterface;
......@@ -64,6 +65,13 @@ abstract class Base extends PluginBase implements FieldPermissionTypeInterface,
return $this->pluginDefinition['description'];
}
/**
* {@inheritdoc}
*/
public function appliesToField(FieldDefinitionInterface $field_definition): bool {
return TRUE;
}
/**
* Determines if the given account may view the field, regardless of entity.
*
......
......@@ -5,6 +5,7 @@ namespace Drupal\field_permissions\Plugin;
use Drupal\Component\Plugin\DerivativeInspectionInterface;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Session\AccountInterface;
/**
......@@ -79,4 +80,15 @@ interface FieldPermissionTypeInterface extends PluginInspectionInterface, Deriva
*/
public function hasFieldAccess($operation, EntityInterface $entity, AccountInterface $account);
/**
* Checks whether this plugin can be applied to a certain field.
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The field definition.
*
* @return bool
* Whether this plugin can be applied to a certain field.
*/
public function appliesToField(FieldDefinitionInterface $field_definition): bool;
}
......@@ -3,6 +3,7 @@
namespace Drupal\field_permissions_test\Plugin\FieldPermissionType;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\field_permissions\Plugin\FieldPermissionType\Base;
use Drupal\field_permissions\Plugin\CustomPermissionsInterface;
......@@ -23,6 +24,10 @@ class TestAccess extends Base implements CustomPermissionsInterface {
* {@inheritdoc}
*/
public function hasFieldAccess($operation, EntityInterface $entity, AccountInterface $account) {
// Flag that this method was called.
// @see \Drupal\Tests\field_permissions\Kernel\Plugin\FieldPermissionType\ManagerTest::testAppliesToField()
\Drupal::state()->set('field_permissions_test.called_TestAccess::hasFieldAccess', TRUE);
if ($operation === 'view') {
return $account->hasPermission('foo access');
}
......@@ -47,4 +52,13 @@ class TestAccess extends Base implements CustomPermissionsInterface {
];
}
/**
* {@inheritdoc}
*/
public function appliesToField(FieldDefinitionInterface $field_definition): bool {
// The state variable is used in tests as a switch.
// @see \Drupal\Tests\field_permissions\Functional\FieldPermissionsFieldConfigEditFormTest::testAppiesToField()
return \Drupal::state()->get('field_permissions_test.applies_to_field', TRUE);
}
}
<?php
namespace Drupal\Tests\field_permissions\Functional;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the field config edit form.
*
* @group field_permissions
*/
class FieldPermissionsFieldConfigEditFormTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'field_permissions_test',
'node',
'field_ui',
];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* Tests that plugins can opt-out for a given field.
*
* @covers \Drupal\field_permissions\Plugin\FieldPermissionTypeInterface::appliesToField
*/
public function testAppliesToField(): void {
$node_type = NodeType::create(['type' => 'page']);
$node_type->save();
node_add_body_field($node_type);
$this->drupalLogin($this->createUser([
'administer field permissions',
'administer node fields',
]));
$this->drupalGet('/admin/structure/types/manage/page/fields/node.page.body');
$assert = $this->assertSession();
// All plugins are exposed on the field config edit form.
$assert->pageTextContains('Field visibility and permissions');
$assert->fieldExists('Not set');
$assert->fieldExists('Private');
$assert->fieldExists('Test type');
$assert->fieldExists('Custom permissions');
// Allow 'test_access' plugin to opt-out.
\Drupal::state()->set('field_permissions_test.applies_to_field', FALSE);
$this->getSession()->reload();
// Check that 'test_access' is not exposed anymore on the form.
$assert->fieldExists('Not set');
$assert->fieldExists('Private');
$assert->fieldNotExists('Test type');
$assert->fieldExists('Custom permissions');
}
}
......@@ -3,6 +3,7 @@
namespace Drupal\Tests\field_permissions\Kernel\Plugin\FieldPermissionType;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\user\Traits\UserCreationTrait;
......@@ -97,4 +98,46 @@ class ManagerTest extends KernelTestBase {
$this->assertSame($expected, array_keys($definitions));
}
/**
* Tests FieldPermissionTypeInterface::appliesToField().
*
* @covers \Drupal\field_permissions\Plugin\FieldPermissionTypeInterface::appliesToField
*/
public function testAppliesToField(): void {
$state = $this->container->get('state');
$service = $this->container->get('field_permissions.permissions_service');
FieldStorageConfig::create([
'type' => 'string',
'entity_type' => 'entity_test',
'field_name' => 'test_foo',
'third_party_settings' => [
'field_permissions' => [
'permission_type' => 'test_access',
],
],
])->save();
$field_config = FieldConfig::create([
'entity_type' => 'entity_test',
'bundle' => 'entity_test',
'field_name' => 'test_foo',
]);
$field_config->save();
$entity = EntityTest::create();
$service->getFieldAccess('view', $entity->get('test_foo'), $this->account, $field_config);
// Check that, by default, the plugin ::hasFieldAccess() method is called.
$this->assertTrue($state->get('field_permissions_test.called_TestAccess::hasFieldAccess'));
// Reset the state variable.
$state->delete('field_permissions_test.called_TestAccess::hasFieldAccess');
// Simulate that 'test_access' ::appliesToField() returns FALSE.
$state->set('field_permissions_test.applies_to_field', FALSE);
// Check that TestAccess::hasFieldAccess() hasn't been called.
$this->assertNull($state->get('field_permissions_test.called_TestAccess::hasFieldAccess'));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment