Puncte:0

Plugin de blocare personalizat: acordați acces pentru a edita formularul

drapel in

Creez un plugin de bloc personalizat cu opțiuni de configurare personalizate (blockForm()).

Aș dori să permit editorilor de conținut să editeze configurația acestui bloc, fără a le acorda permisiunea de „administrare blocuri”. De asemenea, nu vreau ca ei să creeze noi instanțe de bloc.

Aș dori să evit să instalez un modul suplimentar, cum ar fi block_permissions, deoarece aceasta ar introduce o gamă largă de setări sau permisiuni pentru toate blocurile, nu doar pentru blocul specific pe care îl creez.

De asemenea, nu vreau ca acesta să fie un bloc de „conținut” cu „câmpuri”. Vreau să știu cum se poate face acest lucru cu un bloc personalizat bazat pe plugin.

EDITARE / ACTUALIZARE
(pe baza răspunsurilor și discuțiilor)

Răspunsul existent este perfect, dacă obiectivul dvs. este cel descris în întrebare.

Cu toate acestea, întreaga premisă are o problemă: întregul bloc de plasare va fi exportat în config și suprascris la implementare. Aceasta înseamnă că orice setări controlate de utilizator vor fi distruse la următoarea versiune. Deci acest lucru nu este durabil. O entitate de bloc de conținut poate fi utilizată pentru a permite o împărțire adecvată.

Puncte:1
drapel cn

Dacă un utilizator nu are permisiunea de administrator pentru un tip de entitate, aceasta nu înseamnă că nu puteți permite operațiuni specifice asupra anumitor entități existente.

De exemplu, editorii de conținut cărora le-ați dat permisiunea de a administra conținut pot, de asemenea, să actualizeze blocuri ale pluginului dvs. de blocare personalizat:

utilizați Drupal\block\Entity\Block;
utilizați Drupal\Core\Access\AccessResult;
utilizați Drupal\Core\Session\AccountInterface;

/**
 * Implementează hook_ENTITY_TYPE_access() pentru tipul de entitate „block”.
 */
function mymodule_block_access(Blocați $bloc, $operațiune, AccountInterface $cont) {
  if ($operation == 'actualizare'
    && $block->getPluginId() == 'custom_block_plugin_id'
    // Ultima condiție este necesară doar dacă trucul de jos este folosit cu
    // `$block_entity->createDuplicate()->access('update')`.
    && $block->id() !== NULL
  ) {
    returnează AccessResult::allowedIfHasPermission($cont, 'administer nodes');
  }
  returnează AccessResult::neutral();
}

De asemenea, trebuie să modificați formularul pentru a nu redirecționa la trimiterea către o pagină la care utilizatorul nu are acces. Sau trimiteți la formularul de editare cu un șir de interogare de destinație care indică către o altă pagină.


(EDIT de @donquixote)

Dacă doriți să restricționați accesul la alte elemente din pagină, o puteți face ca mai jos.
Acesta este un pic fragil, deoarece presupune o structură foarte specifică a formei.

/**
 * Implementează hook_form_FORM_ID_alter() pentru „block_form”.
 */
funcția mymodule_form_block_form_alter(array &$form, FormStateInterface $form_state, șir $form_id) {
  $form_object = $form_state->getFormObject();
  dacă (!$form_object instanță de BlockForm) {
    întoarcere;
  }
  /** @var Block $block_entity */
  $block_entity = $form_object->getEntity();
  if ($block_entity->getPluginId() !== 'custom_block_plugin_id') {
    întoarcere;
  }
  if ($block_entity->createDuplicate()->access('actualizare')) {
    // Utilizatorul are acces general pentru a actualiza acest bloc.
    întoarcere;
  }
  // Utilizatorului i sa dat acces numai prin mymodule_block_access().
  // Aceștia ar trebui să editeze doar setările specifice pluginului, nu să schimbe locul
  // blocul este plasat.
  foreach (['vizibility', 'id', 'weight', 'region'] as $key) {
    if (isset($form[$key])) {
      $form[$key]['#access'] = FALSE;
    }
  }
  foreach (['label', 'label_display'] ca $key) {
    if (isset($form['settings'][$key])) {
      $form['settings'][$key]['#access'] = FALSE;
    }
  }
  foreach (['șterge'] ca $key) {
    if (isset($form['actions'][$key])) {
      $form['actions'][$key]['#access'] = FALSE;
    }
  }
}
drapel in
Mulțumesc, funcționează! Totuși, acum am nevoie și de `hook_form_block_form_alter()` pentru a seta `'#access' => FALSE` pe toate elementele pe care nu vreau să le editeze. Care este cea mai mare parte din restul acestei forme.
drapel in
Destinația este deja în regulă, deoarece utilizatorii vor accesa acest formular prin link-urile contextuale.
drapel in
Hopa, am presupus că va trebui să confirmați modificările..
drapel in
Anunțați-mă dacă editarea este ok sau nu ezitați să o modificați. Pot să fac și un răspuns separat, dar nu vreau să „fur” bifa „răspuns acceptat”.
4uk4 avatar
drapel cn
Puteți, dacă doriți, să modificați elementele formularului din pluginul bloc personalizat direct, suprascriind buildConfigurationForm().
drapel in
Aceasta acoperă doar elementele din subformularul `$form['settings']`. Setările de vizibilitate, plasarea regiunii și opțiunea de a elimina blocarea trebuie încă tratate în `hook_form_alter()`.
drapel in
Totuși, `\Drupal::currentUser()->hasPermission('administer blocks')` este puțin ciudat. În schimb, aș dori să verific dacă utilizatorul _ar_ avea acces de blocare la actualizare dacă nu ar fi fost pentru `hook_block_access()` personalizat.
4uk4 avatar
drapel cn
OK, deci cârligul de modificare a formularului pare a fi cel mai simplu mod de a controla toate elementele de formular. Dacă trebuie să faceți mai multe ajustări la un moment dat, ar putea fi necesar să extindeți formularul de bloc. Am văzut că constructorul de layout are o mulțime de forme de bloc diferite pentru sarcini diferite.
4uk4 avatar
drapel cn
Cred că acest lucru este în regulă, entitatea de configurare a blocului folosește aceasta simplificată pentru toate permisiunile definite în tipul de entitate.
drapel in
Este posibil ca „administrarea blocurilor” să nu fie potrivită atunci când utilizați un modul suplimentar pentru un control mai precis al accesului. Am adăugat un truc în cod cu `$block_entity->createDuplicate()->access('update')`. Acest lucru pare să facă truc și, de asemenea, va ocoli memoria cache, sper...
drapel in
Rezultatul accesului este stocat în cache pentru fiecare entitate sau trebuie să adăugăm o altă etichetă cache?
drapel in
Observ o altă problemă cu aceasta: toate acestea sunt exportate în config, astfel încât orice modificări ale utilizatorului ar fi suprascrise atunci când config este importată la următoarea implementare. Acum sunt aproape convins că acesta este modul greșit de a face lucrurile și chiar ar trebui să folosesc un bloc de conținut.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.