Рейтинг:0

Плагин пользовательского блока: Дайте доступ к форме редактирования

флаг in

Я создаю плагин пользовательского блока с настраиваемыми параметрами конфигурации (блокФорма()).

Я хотел бы разрешить редакторам контента редактировать конфигурацию этого блока, не давая им разрешения «администрировать блоки». Кроме того, я не хочу, чтобы они создавали новые экземпляры блоков.

Я хотел бы избежать установки дополнительного модуля, такого как block_permissions, так как это введет широкий спектр настроек или разрешений для всех блоков, а не только для конкретного блока, который я создаю.

Я также не хочу, чтобы это был блок «контента» с «полями». Я хочу знать, как это можно сделать с помощью пользовательского блока на основе плагина.

РЕДАКТИРОВАТЬ/ОБНОВИТЬ
(на основе ответов и обсуждения)

Существующий ответ является точным, если ваша цель соответствует описанию в вопросе.

Однако у всей предпосылки есть одна проблема: все размещение блоков будет экспортировано в конфигурацию и перезаписано при развертывании. Это означает, что любые настройки, контролируемые пользователем, будут уничтожены в следующем выпуске. Так что это не устойчиво. Объект блока контента можно использовать для правильного разделения.

Рейтинг:1
флаг cn

Если у пользователя нет прав администратора для типа объекта, это не означает, что вы не можете разрешить определенные операции с конкретными существующими объектами.

Например, редакторы контента, которым вы предоставили разрешение на администрирование контента, также могут обновлять блоки вашего плагина настраиваемых блоков:

используйте Drupal\block\Entity\Block;
используйте Drupal\Core\Access\AccessResult;
используйте Drupal\Core\Session\AccountInterface;

/**
 * Реализует hook_ENTITY_TYPE_access() для типа объекта "блок".
 */
функция mymodule_block_access (блок $ блок, $ операция, учетная запись $ AccountInterface) {
  если ($operation == 'обновить'
    && $block->getPluginId() == 'custom_block_plugin_id'
    // Последнее условие необходимо только в том случае, если трюк снизу используется с
    // `$block_entity->createDuplicate()->access('update')`.
    && $block->id() !== NULL
  ) {
    return AccessResult::allowedIfHasPermission($account, 'администрировать узлы');
  }
  вернуть AccessResult::neutral();
}

Вам также необходимо изменить форму, чтобы она не перенаправляла при отправке на страницу, к которой у пользователя нет доступа. Или свяжите форму редактирования с целевой строкой запроса, указывающей на другую страницу.


(РЕДАКТИРОВАТЬ @donquixote)

Если вы хотите ограничить доступ к другим элементам на странице, вы можете сделать это, как показано ниже.
Это немного хрупко, потому что предполагает очень специфическую структуру формы.

/**
 * Реализует hook_form_FORM_ID_alter() для 'block_form'.
 */
function mymodule_form_block_form_alter (массив и $ форма, FormStateInterface $ form_state, строка $ form_id) {
  $form_object = $form_state->getFormObject();
  если (!$form_object instanceof BlockForm) {
    возвращаться;
  }
  /** @var Блок $block_entity */
  $block_entity = $form_object->getEntity();
  если ($block_entity->getPluginId() !== 'custom_block_plugin_id') {
    возвращаться;
  }
  если ($block_entity->createDuplicate()->доступ('обновление')) {
    // Пользователь имеет общий доступ для обновления этого блока.
    возвращаться;
  }
  // Пользователю был предоставлен доступ только через mymodule_block_access().
  // Они должны редактировать только определенные настройки плагина, а не менять, где
  // блок размещен.
  foreach (['видимость', 'id', 'вес', 'регион'] как $key) {
    если (isset($form[$key])) {
      $form[$key]['#access'] = FALSE;
    }
  }
  foreach (['label', 'label_display'] как $key) {
    если (isset($form['settings'][$key])) {
      $form['settings'][$key]['#access'] = FALSE;
    }
  }
  foreach (['удалить'] как $key) {
    если (isset($form['actions'][$key])) {
      $form['actions'][$key]['#access'] = FALSE;
    }
  }
}
флаг in
Спасибо, это работает! Однако теперь мне также нужно, чтобы `hook_form_block_form_alter()` установил `'#access' => FALSE` для всех элементов, которые я не хочу редактировать. Что составляет большую часть остальной части этой формы.
флаг in
Место назначения уже подходит, потому что пользователи будут получать доступ к этой форме через контекстные ссылки.
флаг in
Упс, я предполагал, что вам придется подтвердить правки..
флаг in
Дайте мне знать, если редактирование в порядке, или не стесняйтесь изменять его. Я также могу сделать это отдельным ответом, но я не хочу «красть» галочку «принятый ответ».
4uk4 avatar
флаг cn
Вы можете, если хотите, изменить элементы формы в плагине пользовательского блока напрямую, переопределив buildConfigurationForm().
флаг in
Это относится только к элементам внутри подформы `$form['settings']`. Настройки видимости, размещение области и возможность удаления блока по-прежнему требуют обработки в `hook_form_alter()`.
флаг in
Кстати, `\Drupal::currentUser()->hasPermission('администрирование блоков')` немного неудобно. Вместо этого я хотел бы проверить, будет ли у пользователя доступ к обновлению блока, если бы не пользовательский `hook_block_access()`.
4uk4 avatar
флаг cn
Итак, хук изменения формы кажется самым простым способом управления всеми элементами формы. Если вам нужно внести дополнительные корректировки в какой-то момент, может потребоваться расширить форму блока. Я видел, что в построителе макетов есть много разных форм блоков для разных задач.
4uk4 avatar
флаг cn
Я думаю, что это нормально, объект конфигурации блока использует это упрощенное для всех разрешений, определенных в типе объекта.
флаг in
«Административные блоки» могут не подойти при использовании дополнительного модуля для более точного контроля доступа. Я добавил в код трюк с `$block_entity->createDuplicate()->access('update')`. Кажется, это помогает, а также, я надеюсь, обойдет кеш.
флаг in
Кэшируется ли результат доступа для каждого объекта, или нам нужно добавить еще один тег кеша?
флаг in
Я заметил еще одну проблему: все это экспортируется в конфигурацию, поэтому любые пользовательские изменения будут перезаписаны при импорте конфигурации при следующем развертывании. Теперь я почти убежден, что это неправильный способ делать что-то, и мне действительно следует использовать блок контента.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.