123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746 |
- <?php
- /**
- * @file
- * Domain-based access control for content.
- */
- use Drupal\Core\Field\FieldDefinitionInterface;
- use Drupal\Core\Field\FieldItemListInterface;
- use Drupal\node\NodeInterface;
- use Drupal\Core\Access\AccessResult;
- use Drupal\Core\Entity\EntityInterface;
- use Drupal\Core\Session\AccountInterface;
- use Drupal\Core\Form\FormState;
- /**
- * The name of the node access control field.
- */
- const DOMAIN_ACCESS_FIELD = 'field_domain_access';
- /**
- * The name of the all affiliates field.
- */
- const DOMAIN_ACCESS_ALL_FIELD = 'field_domain_all_affiliates';
- /**
- * Implements hook_node_grants().
- */
- function domain_access_node_grants(AccountInterface $account, $op) {
- $grants = [];
- /** @var \Drupal\domain\Entity\Domain $active */
- $active = \Drupal::service('domain.negotiator')->getActiveDomain();
- if (empty($active)) {
- $active = \Drupal::entityTypeManager()->getStorage('domain')->loadDefaultDomain();
- }
- // No domains means no permissions.
- if (empty($active)) {
- return $grants;
- }
- $id = $active->getDomainId();
- // Advanced grants for edit/delete require permissions.
- /** @var \Drupal\user\UserInterface $user */
- $user = \Drupal::entityTypeManager()->getStorage('user')->load($account->id());
- $user_domains = \Drupal::service('domain_access.manager')->getAccessValues($user);
- // Grants for view are simple. Use the active domain and all affiliates.
- // Note that "X to any domain" is a global permission designed for admins.
- if ($op == 'view') {
- $grants['domain_id'][] = $id;
- $grants['domain_site'][] = 0;
- if ($user->hasPermission('view unpublished domain content')) {
- if ($user->hasPermission('publish to any domain') || in_array($id, $user_domains) || !empty($user->get(DOMAIN_ACCESS_ALL_FIELD)->value)) {
- $grants['domain_unpublished'][] = $id;
- }
- }
- }
- elseif ($op == 'update' && $user->hasPermission('edit domain content')) {
- if ($user->hasPermission('publish to any domain') || in_array($id, $user_domains) || !empty($user->get(DOMAIN_ACCESS_ALL_FIELD)->value)) {
- $grants['domain_id'][] = $id;
- }
- }
- elseif ($op == 'delete' && $user->hasPermission('delete domain content')) {
- if ($user->hasPermission('publish to any domain') || in_array($id, $user_domains) || !empty($user->get(DOMAIN_ACCESS_ALL_FIELD)->value)) {
- $grants['domain_id'][] = $id;
- }
- }
- return $grants;
- }
- /**
- * Implements hook_node_access_records().
- */
- function domain_access_node_access_records(NodeInterface $node) {
- $grants = [];
- // Create grants for each translation of the node. See the report at
- // https://www.drupal.org/node/2825419 for the logic here. Note that right
- // now, grants may not be the same for all languages.
- $translations = $node->getTranslationLanguages();
- foreach ($translations as $langcode => $language) {
- $translation = $node->getTranslation($langcode);
- // If there are no domains set, use the current one.
- $domains = \Drupal::service('domain_access.manager')->getAccessValues($translation);
- /** @var \Drupal\domain\DomainInterface $active */
- if (empty($domains) && $active = \Drupal::service('domain.negotiator')->getActiveDomain()) {
- $domains[$active->id()] = $active->getDomainId();
- }
- foreach ($domains as $id => $domainId) {
- /** @var \Drupal\domain\DomainInterface $domain */
- if ($domain = \Drupal::entityTypeManager()->getStorage('domain')->load($id)) {
- $grants[] = [
- 'realm' => ($translation->isPublished()) ? 'domain_id' : 'domain_unpublished',
- 'gid' => $domain->getDomainId(),
- 'grant_view' => 1,
- 'grant_update' => 1,
- 'grant_delete' => 1,
- 'langcode' => $langcode,
- ];
- }
- }
- // Set the domain_site grant.
- if (!empty($translation->get(DOMAIN_ACCESS_ALL_FIELD)->value) && $translation->isPublished()) {
- $grants[] = [
- 'realm' => 'domain_site',
- 'gid' => 0,
- 'grant_view' => 1,
- 'grant_update' => 0,
- 'grant_delete' => 0,
- 'langcode' => $langcode,
- ];
- }
- // Because of language translation, we must save a record for each language.
- // even if that record adds no permissions, as this one does.
- else {
- $grants[] = [
- 'realm' => 'domain_site',
- 'gid' => 1,
- 'grant_view' => 0,
- 'grant_update' => 0,
- 'grant_delete' => 0,
- 'langcode' => $langcode,
- ];
- }
- }
- return $grants;
- }
- /**
- * Implements hook_ENTITY_TYPE_presave().
- *
- * Fires only if Devel Generate module is present, to assign test nodes to
- * domains.
- */
- function domain_access_node_presave(EntityInterface $node) {
- domain_access_presave_generate($node);
- }
- /**
- * Implements hook_ENTITY_TYPE_presave().
- *
- * Fires only if Devel Generate module is present, to assign test nodes to
- * domains.
- */
- function domain_access_user_presave(EntityInterface $account) {
- domain_access_presave_generate($account);
- }
- /**
- * Handles presave operations for devel generate.
- */
- function domain_access_presave_generate(EntityInterface $entity) {
- // There is a core bug https://www.drupal.org/node/2609252 that causes a
- // fatal database errors if the boolean DOMAIN_ACCESS_ALL_FIELD is set when
- // a user cannot access the field. See domain_access_entity_field_access().
- // To overcome this issue, we cast the boolean to integer, which prevents the
- // failure.
- $value = (int) $entity->get(DOMAIN_ACCESS_ALL_FIELD)->value;
- $entity->set(DOMAIN_ACCESS_ALL_FIELD, $value);
- // Handle devel module settings.
- $exists = \Drupal::moduleHandler()->moduleExists('devel_generate');
- $values = [];
- if ($exists && isset($entity->devel_generate)) {
- // If set by the form.
- if (isset($entity->devel_generate['domain_access'])) {
- $selection = array_filter($entity->devel_generate['domain_access']);
- if (isset($selection['random-selection'])) {
- $domains = \Drupal::entityTypeManager()->getStorage('domain')->loadMultiple();
- $values[DOMAIN_ACCESS_FIELD] = array_rand($domains, ceil(rand(1, count($domains))));
- }
- else {
- $values[DOMAIN_ACCESS_FIELD] = array_keys($selection);
- }
- }
- if (isset($entity->devel_generate['domain_all'])) {
- $selection = $entity->devel_generate['domain_all'];
- if ($selection == 'random-selection') {
- $values[DOMAIN_ACCESS_ALL_FIELD] = rand(0, 1);
- }
- else {
- $values[DOMAIN_ACCESS_ALL_FIELD] = ($selection = 'yes' ? 1 : 0);
- }
- }
- foreach ($values as $name => $value) {
- $entity->set($name, $value);
- }
- }
- }
- /**
- * Implements hook_form_FORM_ID_alter().
- *
- * Add options for domains when using Devel Generate.
- */
- function domain_access_form_devel_generate_form_content_alter(&$form, &$form_state, $form_id) {
- // Add our element to the Devel generate form.
- $form['submit']['#weight'] = 10;
- $list = ['random-selection' => t('Random selection')];
- $list += \Drupal::entityTypeManager()->getStorage('domain')->loadOptionsList();
- $form['domain_access'] = [
- '#title' => t('Domains'),
- '#type' => 'checkboxes',
- '#options' => $list,
- '#weight' => 2,
- '#multiple' => TRUE,
- '#size' => count($list) > 5 ? 5 : count($list),
- '#default_value' => ['random-selection'],
- '#description' => t('Sets the domains for created nodes. Random selection overrides other choices.'),
- ];
- $form['domain_all'] = [
- '#title' => t('Send to all affiliates'),
- '#type' => 'radios',
- '#options' => [
- 'random-selection' => t('Random selection'),
- 'yes' => t('Yes'),
- 'no' => t('No'),
- ],
- '#default_value' => 'random-selection',
- '#weight' => 3,
- '#description' => t('Sets visibility across all affiliates.'),
- ];
- }
- /**
- * Implements hook_form_FORM_ID_alter().
- *
- * Add options for domains when using Devel Generate.
- */
- function domain_access_form_devel_generate_form_user_alter(&$form, &$form_state, $form_id) {
- domain_access_form_devel_generate_form_content_alter($form, $form_state, $form_id);
- }
- /**
- * Implements hook_form_BASE_FORM_ID_alter() for \Drupal\node\NodeForm.
- *
- * Move Domain Access fields to an advanced tab like other node settings.
- */
- function domain_access_form_node_form_alter(&$form, FormState $form_state, $form_id) {
- $move_enabled = \Drupal::config('domain_access.settings')->get('node_advanced_tab');
- if (
- $move_enabled && isset($form[DOMAIN_ACCESS_FIELD]) &&
- isset($form[DOMAIN_ACCESS_ALL_FIELD]) &&
- empty($form[DOMAIN_ACCESS_FIELD]['#group']) &&
- empty($form[DOMAIN_ACCESS_ALL_FIELD]['#group'])
- ) {
- // Move to the tabs on the entity form.
- $form[DOMAIN_ACCESS_FIELD]['#group'] = 'domain';
- $form[DOMAIN_ACCESS_ALL_FIELD]['#group'] = 'domain';
- $form['domain'] = [
- '#type' => 'details',
- '#open' => (bool) \Drupal::config('domain_access.settings')->get('node_advanced_tab_open'),
- '#title' => t('Domain settings'),
- '#group' => 'advanced',
- '#attributes' => [
- 'class' => ['node-form-options'],
- ],
- '#attached' => [
- 'library' => ['node/drupal.node'],
- ],
- '#weight' => 100,
- '#optional' => TRUE,
- ];
- }
- // Add the options hidden from the user silently to the form.
- $manager = \Drupal::service('domain.element_manager');
- $form = $manager->setFormOptions($form, $form_state, DOMAIN_ACCESS_FIELD);
- }
- /**
- * Implements hook_form_BASE_FORM_ID_alter() for \Drupal\user\UserForm.
- *
- * Handle settings that the user cannot access.
- */
- function domain_access_form_user_form_alter(&$form, &$form_state, $form_id) {
- // Add the options hidden from the user silently to the form.
- $manager = \Drupal::service('domain.element_manager');
- $form = $manager->setFormOptions($form, $form_state, DOMAIN_ACCESS_FIELD);
- }
- /**
- * Implements hook_domain_references_alter().
- */
- function domain_access_domain_references_alter($query, $account, $context) {
- // Restrict domains by editorial assignment.
- if ($context['field_type'] != 'editor') {
- return;
- }
- switch ($context['entity_type']) {
- case 'node':
- if ($account->hasPermission('publish to any domain')) {
- break;
- }
- elseif ($account->hasPermission('publish to any assigned domain')) {
- if (!empty($account->get(DOMAIN_ACCESS_ALL_FIELD)->value)) {
- break;
- }
- $allowed = \Drupal::service('domain_access.manager')->getAccessValues($account);
- $query->condition('id', array_keys($allowed), 'IN');
- }
- else {
- // Remove all options.
- $query->condition('id', '-no-possible-match-');
- }
- break;
- case 'user':
- if ($account->hasPermission('assign editors to any domain')) {
- // Do nothing.
- }
- elseif ($account->hasPermission('assign domain editors')) {
- if (!empty($account->get(DOMAIN_ACCESS_ALL_FIELD)->value)) {
- break;
- }
- $allowed = \Drupal::service('domain_access.manager')->getAccessValues($account);
- $query->condition('id', array_keys($allowed), 'IN');
- }
- else {
- // Remove all options.
- $query->condition('id', '-no-possible-match-');
- }
- break;
- default:
- // No action taken.
- break;
- }
- }
- /**
- * Implements hook_node_access().
- */
- function domain_access_node_access(NodeInterface $node, $op, AccountInterface $account) {
- static $active_domain;
- if (!isset($active_domain)) {
- // Ensure that the loader has run. In some tests, the kernel event has not.
- $active = \Drupal::service('domain.negotiator')->getActiveDomain();
- if (empty($active)) {
- $active = \Drupal::service('domain.negotiator')->getActiveDomain(TRUE);
- }
- $active_domain = $active;
- }
- // Check to see that we have a valid active domain.
- // Without one, we cannot assert an opinion about access.
- if (!$active_domain || empty($active_domain->getDomainId())) {
- return AccessResult::neutral();
- }
- $type = $node->bundle();
- $manager = \Drupal::service('domain_access.manager');
- $allowed = FALSE;
- // In order to access update or delete, the user must be able to View.
- if ($op == 'view' && $manager->checkEntityAccess($node, $account)) {
- /** @var \Drupal\user\UserInterface $user */
- if ($node->isPublished()) {
- $allowed = TRUE;
- }
- elseif ($account->hasPermission('view unpublished domain content')) {
- $allowed = TRUE;
- }
- }
- if ($op == 'update') {
- if ($account->hasPermission('update ' . $type . ' content on assigned domains') && $manager->checkEntityAccess($node, $account)) {
- $allowed = TRUE;
- }
- elseif ($account->hasPermission('edit domain content') && $manager->checkEntityAccess($node, $account)) {
- $allowed = TRUE;
- }
- }
- if ($op == 'delete') {
- if ($account->hasPermission('delete ' . $type . ' content on assigned domains') && $manager->checkEntityAccess($node, $account)) {
- $allowed = TRUE;
- }
- elseif ($account->hasPermission('delete domain content') && $manager->checkEntityAccess($node, $account)) {
- $allowed = TRUE;
- }
- }
- if ($allowed) {
- return AccessResult::allowed()
- ->cachePerPermissions()
- ->cachePerUser()
- ->addCacheableDependency($node);
- }
- // No opinion.
- return AccessResult::neutral();
- }
- /**
- * Implements hook_node_create_access().
- *
- * @link https://www.drupal.org/node/2348203
- */
- function domain_access_node_create_access(AccountInterface $account, $context, $entity_bundle) {
- // Check to see that we have a valid active domain.
- // Without one, we cannot assert an opinion about access.
- /** @var \Drupal\domain\DomainInterface $active */
- if ($active = \Drupal::service('domain.negotiator')->getActiveDomain()) {
- $id = $active->getDomainId();
- }
- else {
- return AccessResult::neutral();
- }
- // Load the full user record.
- $user = \Drupal::entityTypeManager()->getStorage('user')->load($account->id());
- $user_domains = \Drupal::service('domain_access.manager')->getAccessValues($user);
- if (($account->hasPermission('create ' . $entity_bundle . ' content on assigned domains')
- || $account->hasPermission('create domain content'))
- && in_array($id, $user_domains)) {
- // Note the cache context here!
- return AccessResult::allowed()->addCacheContexts(['user.permissions', 'url.site']);
- }
- // No opinion.
- return AccessResult::neutral();
- }
- /**
- * Implements hook_entity_field_access().
- */
- function domain_access_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
- // Hide the domain access fields from the entity add/edit forms
- // when the user cannot access them.
- if ($operation != 'edit') {
- return AccessResult::neutral();
- }
- // The entity the field is attached to.
- $entity = $items->getEntity();
- if ($field_definition->getName() == DOMAIN_ACCESS_FIELD) {
- if ($entity instanceof AccountInterface) {
- $access = AccessResult::allowedIfHasPermissions($account, [
- 'assign domain editors',
- 'assign editors to any domain',
- ], 'OR');
- }
- elseif ($entity instanceof NodeInterface) {
- // Treat any other entity as content.
- $access = AccessResult::allowedIfHasPermissions($account, [
- 'publish to any domain',
- 'publish to any assigned domain',
- ], 'OR');
- }
- // allowedIfHasPermissions returns allowed() or neutral().
- // In this case, we want it to be forbidden,
- // if user doesn't have the permissions above.
- if (isset($access) && !$access->isAllowed()) {
- return AccessResult::forbidden();
- }
- }
- // Check permissions on the All Affiliates field.
- elseif ($field_definition->getName() == DOMAIN_ACCESS_ALL_FIELD) {
- if ($entity instanceof AccountInterface) {
- return AccessResult::forbiddenIf(!$account->hasPermission('assign editors to any domain'));
- }
- elseif ($entity instanceof NodeInterface) {
- // Treat any other entity as content.
- return AccessResult::forbiddenIf(!$account->hasPermission('publish to any domain'));
- }
- }
- return AccessResult::neutral();
- }
- /**
- * Implements hook_ENTITY_TYPE_insert().
- *
- * Creates our fields when new node types are created.
- */
- function domain_access_node_type_insert(EntityInterface $entity) {
- /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $entity */
- if (!$entity->isSyncing()) {
- // Do not fire hook when config sync in progress.
- domain_access_confirm_fields('node', $entity->id());
- }
- }
- /**
- * Implements hook_ENTITY_TYPE_insert().
- *
- * In some cases, form display modes are not set when the node type is created.
- * be sure to update our field definitions on creation of form_display for
- * node types.
- */
- function domain_access_entity_form_display_insert(EntityInterface $entity) {
- if (!$entity->isSyncing() && $entity->getTargetEntityTypeId() == 'node' && $bundle = $entity->getTargetBundle()) {
- domain_access_confirm_fields('node', $bundle);
- }
- }
- /**
- * Creates our fields for an entity bundle.
- *
- * @param string $entity_type
- * The entity type being created. Node and user are supported.
- * @param string $bundle
- * The bundle being created.
- * @param array $text
- * The text to use for the field. Keys are:
- * 'name' -- the lower-case, human-readable name of the entity.
- * 'label' -- the form label for the all affiliates field.
- * 'description' -- the help text for the all affiliates field.
- *
- * If calling this function for entities other than user or node, it is the
- * caller's responsibility to provide this text.
- *
- * This function is here for convenience during installation. It is not really
- * an API function. Modules wishing to add fields to non-node entities must
- * provide their own field storage. See the field storage YML sample in
- * tests/modules/domain_access_test for an example of field storage
- * definitions.
- *
- * @see domain_access_node_type_insert()
- * @see domain_access_install()
- */
- function domain_access_confirm_fields($entity_type, $bundle, array $text = []) {
- // We have reports that importing config causes this function to fail.
- try {
- $text['node'] = [
- 'name' => 'content',
- 'label' => 'Send to all affiliates',
- 'description' => 'Make this content available on all domains.',
- ];
- $text['user'] = [
- 'name' => 'user',
- 'label' => 'Editor for all affiliates',
- 'description' => 'Make this user an editor on all domains.',
- ];
- $id = $entity_type . '.' . $bundle . '.' . DOMAIN_ACCESS_FIELD;
- $field_storage = \Drupal::entityTypeManager()->getStorage('field_config');
- if (!$field = $field_storage->load($id)) {
- $field = [
- 'field_name' => DOMAIN_ACCESS_FIELD,
- 'entity_type' => $entity_type,
- 'label' => 'Domain Access',
- 'bundle' => $bundle,
- // Users should not be required to be a domain editor.
- 'required' => $entity_type !== 'user',
- 'description' => 'Select the affiliate domain(s) for this ' . $text[$entity_type]['name'],
- 'default_value_callback' => 'Drupal\domain_access\DomainAccessManager::getDefaultValue',
- 'settings' => [
- 'handler' => 'default:domain',
- // Handler_settings are deprecated but seem to be necessary here.
- 'handler_settings' => [
- 'target_bundles' => NULL,
- 'sort' => ['field' => 'weight', 'direction' => 'ASC'],
- ],
- 'target_bundles' => NULL,
- 'sort' => ['field' => 'weight', 'direction' => 'ASC'],
- ],
- ];
- $field_config = $field_storage->create($field);
- $field_config->save();
- }
- // Assign the all affiliates field.
- $id = $entity_type . '.' . $bundle . '.' . DOMAIN_ACCESS_ALL_FIELD;
- if (!$field = $field_storage->load($id)) {
- $field = [
- 'field_name' => DOMAIN_ACCESS_ALL_FIELD,
- 'entity_type' => $entity_type,
- 'label' => $text[$entity_type]['label'],
- 'bundle' => $bundle,
- 'required' => FALSE,
- 'description' => $text[$entity_type]['description'],
- ];
- $field_config = $field_storage->create($field);
- $field_config->save();
- }
- // Tell the form system how to behave. Default to radio buttons.
- if ($display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load($entity_type . '.' . $bundle . '.default')) {
- $display->setComponent(DOMAIN_ACCESS_FIELD, [
- 'type' => 'options_buttons',
- 'weight' => 40,
- ])->setComponent(DOMAIN_ACCESS_ALL_FIELD, [
- 'type' => 'boolean_checkbox',
- 'settings' => ['display_label' => 1],
- 'weight' => 41,
- ])->save();
- }
- }
- catch (Exception $e) {
- \Drupal::logger('domain_access')->notice('Field installation failed.');
- }
- }
- /**
- * Implements hook_views_data_alter().
- */
- function domain_access_views_data_alter(array &$data) {
- $table = 'node__' . DOMAIN_ACCESS_FIELD;
- $data[$table][DOMAIN_ACCESS_FIELD]['field']['id'] = 'domain_access_field';
- $data[$table][DOMAIN_ACCESS_FIELD . '_target_id']['filter']['id'] = 'domain_access_filter';
- $data[$table][DOMAIN_ACCESS_FIELD . '_target_id']['argument']['id'] = 'domain_access_argument';
- // Current domain filter.
- $data[$table]['current_all'] = [
- 'title' => t('Current domain'),
- 'group' => t('Domain'),
- 'filter' => [
- 'field' => DOMAIN_ACCESS_FIELD . '_target_id',
- 'id' => 'domain_access_current_all_filter',
- 'title' => t('Available on current domain'),
- 'help' => t('Filters out nodes not available on current domain (published to current domain or all affiliates).'),
- ],
- ];
- // Since domains are not stored in the database, relationships cannot be used.
- unset($data[$table][DOMAIN_ACCESS_FIELD]['relationship']);
- // Set the user data.
- $table = 'user__' . DOMAIN_ACCESS_FIELD;
- $data[$table][DOMAIN_ACCESS_FIELD]['field']['id'] = 'domain_access_field';
- $data[$table][DOMAIN_ACCESS_FIELD . '_target_id']['filter']['id'] = 'domain_access_filter';
- $data[$table][DOMAIN_ACCESS_FIELD . '_target_id']['argument']['id'] = 'domain_access_argument';
- // Since domains are not stored in the database, relationships cannot be used.
- unset($data[$table][DOMAIN_ACCESS_FIELD]['relationship']);
- }
- /**
- * Implements hook_ENTITY_TYPE_insert().
- */
- function domain_access_domain_insert($entity) {
- /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $entity */
- if ($entity->isSyncing()) {
- // Do not fire hook when config sync in progress.
- return;
- }
- $id = 'domain_access_add_action.' . $entity->id();
- $controller = \Drupal::entityTypeManager()->getStorage('action');
- if (!$controller->load($id)) {
- /** @var \Drupal\system\Entity\Action $action */
- $action = $controller->create([
- 'id' => $id,
- 'type' => 'node',
- 'label' => t('Add selected content to the @label domain', ['@label' => $entity->label()]),
- 'configuration' => [
- 'domain_id' => $entity->id(),
- ],
- 'plugin' => 'domain_access_add_action',
- ]);
- $action->trustData()->save();
- }
- $remove_id = 'domain_access_remove_action.' . $entity->id();
- if (!$controller->load($remove_id)) {
- /** @var \Drupal\system\Entity\Action $action */
- $action = $controller->create([
- 'id' => $remove_id,
- 'type' => 'node',
- 'label' => t('Remove selected content from the @label domain', ['@label' => $entity->label()]),
- 'configuration' => [
- 'domain_id' => $entity->id(),
- ],
- 'plugin' => 'domain_access_remove_action',
- ]);
- $action->trustData()->save();
- }
- $id = 'domain_access_add_editor_action.' . $entity->id();
- if (!$controller->load($id)) {
- /** @var \Drupal\system\Entity\Action $action */
- $action = $controller->create([
- 'id' => $id,
- 'type' => 'user',
- 'label' => t('Add editors to the @label domain', ['@label' => $entity->label()]),
- 'configuration' => [
- 'domain_id' => $entity->id(),
- ],
- 'plugin' => 'domain_access_add_editor_action',
- ]);
- $action->trustData()->save();
- }
- $remove_id = 'domain_access_remove_editor_action.' . $entity->id();
- if (!$controller->load($remove_id)) {
- /** @var \Drupal\system\Entity\Action $action */
- $action = $controller->create([
- 'id' => $remove_id,
- 'type' => 'user',
- 'label' => t('Remove editors from the @label domain', ['@label' => $entity->label()]),
- 'configuration' => [
- 'domain_id' => $entity->id(),
- ],
- 'plugin' => 'domain_access_remove_editor_action',
- ]);
- $action->trustData()->save();
- }
- }
- /**
- * Implements hook_ENTITY_TYPE_delete().
- */
- function domain_access_domain_delete(EntityInterface $entity) {
- $controller = \Drupal::entityTypeManager()->getStorage('action');
- $actions = $controller->loadMultiple([
- 'domain_access_add_action.' . $entity->id(),
- 'domain_access_remove_action.' . $entity->id(),
- 'domain_access_add_editor_action.' . $entity->id(),
- 'domain_access_remove_editor_action.' . $entity->id(),
- ]);
- foreach ($actions as $action) {
- $action->delete();
- }
- }
- /**
- * Implements hook_form_alter().
- *
- * Find forms that contain the domain access field and allow those to handle
- * default values properly. Note that here we just care if the form saves an
- * entity. We then pass that entity to a helper function.
- *
- * @see domain_access_default_form_values()
- */
- function domain_access_form_alter(&$form, &$form_state, $form_id) {
- if ($object = $form_state->getFormObject() && !empty($object) && is_callable([$object, 'getEntity']) && $entity = $object->getEntity()) {
- domain_access_default_form_values($form, $form_state, $entity);
- }
- }
- /**
- * Defines default values for domain access field.
- *
- * This function is a workaround for a core bug. When the domain access field
- * is not accessible to some users, the existing values are not preserved.
- *
- * @see domain_access_entity_field_access()
- */
- function domain_access_default_form_values(&$form, &$form_state, $entity) {
- // Set domain access default value when the user does not have access
- // to edit the field. This seems to work fine for all affiliates, which
- // suggests a core bug in entity reference handling.
- if (!$entity->isNew() &&
- isset($form['field_domain_access']) &&
- !$form['field_domain_access']['#access'] &&
- empty($form['field_domain_access']['widget']['#default_value'])
- ) {
- // Set the default values correctly.
- $values = \Drupal::service('domain_access.manager')->getAccessValues($entity);
- $form['field_domain_access']['widget']['#default_value'] = array_keys($values);
- }
- }
|