Bagaimana cara menampilkan lebih dari 10 item di widget tautan lengkapi otomatis?

10

Ini adalah pertanyaan tentang modul Tautan. Karena dengan modul Tautan Anda dapat memasukkan tautan eksternal atau internal keduanya, kami sangat bergantung padanya.

Sayangnya jumlah item yang akan ditampilkan dari bidang autocomplete terbatas hingga 10. Kami memiliki banyak node dengan judul yang hampir sama dan karena itu node yang kami cari tidak bisa ditampilkan di bidang autocomplete ketika ada lebih dari 10 judul yang cocok.

Batas dalam hardcode core/lib/Drupal/Core/Entity/EntityAutocompleteMatcher.php. Apakah ada cara yang elegan untuk menambah angka kecil ini dari dalam modul khusus? Apakah saya harus memperpanjang class EntityAutocompleteMatcher? Di mana saya harus meletakkan ekstensi saya dan bagaimana memastikannya dieksekusi dari dalam widget tautan?

leymannx
sumber

Jawaban:

10

Jika Anda dapat hidup dengan mengganti semua batas autocomplete, Anda dapat mengganti layanan inti di Drupal 8;

Layanan yang Anda perlu timpa ada di sini di core.services.yml:

  entity.autocomplete_matcher:
    class: Drupal\Core\Entity\EntityAutocompleteMatcher
    arguments: ['@plugin.manager.entity_reference_selection']

Di modul khusus Anda, tambahkan kelas yang mengimplementasikan ServiceModifierInterface

namespace Drupal\mymodule;

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceModifierInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;

class MyModuleServiceProvider implements ServiceModifierInterface {

  /**
   * Modifies existing service definitions.
   *
   * @param ContainerBuilder $container
   *   The ContainerBuilder whose service definitions can be altered.
   */
  public function alter(ContainerBuilder $container) {

    for ($id = 'entity.autocomplete_matcher'; $container->hasAlias($id); $id = (string) $container->getAlias($id));
    $definition = $container->getDefinition($id);
    $definition->setClass('Drupal\mymodule\Entity\EntityAutocompleteMatcherCustom');
    $container->setDefinition($id, $definition);
  }

}

Kemudian salin EntityAutocompleteMatcher.php ke modul Anda di /src/Entity/EntityAutocompleteMatcherCustom.php

Kemudian perbarui hardcoded 10 ke 50, atau batas apa pun yang Anda inginkan:

namespace Drupal\mymodule\Entity;

use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Tags;
use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface;
use Drupal\Core\Entity\EntityAutocompleteMatcher;

/**
 * Matcher class to get autocompletion results for entity reference.
 */
class EntityAutocompleteMatcherCustom extends EntityAutocompleteMatcher {

  /*
   * {@inheritdoc]
   */
  public function getMatches($target_type, $selection_handler, $selection_settings, $string = '') {

    $matches = array();

    $options = array(
      'target_type' => $target_type,
      'handler' => $selection_handler,
      'handler_settings' => $selection_settings,
    );
    $handler = $this->selectionManager->getInstance($options);

    if (isset($string)) {
      // Get an array of matching entities.
      $match_operator = !empty($selection_settings['match_operator']) ? $selection_settings['match_operator'] : 'CONTAINS';
      // Changing limit from 10 to 50.
      $entity_labels = $handler->getReferenceableEntities($string, $match_operator, 50);

      // Loop through the entities and convert them into autocomplete output.
      foreach ($entity_labels as $values) {
        foreach ($values as $entity_id => $label) {
          $key = "$label ($entity_id)";
          // Strip things like starting/trailing white spaces, line breaks and
          // tags.
          $key = preg_replace('/\s\s+/', ' ', str_replace("\n", '', trim(Html::decodeEntities(strip_tags($key)))));
          // Names containing commas or quotes must be wrapped in quotes.
          $key = Tags::encode($key);
          $matches[] = array('value' => $key, 'label' => $label);
        }
      }
    }

    return $matches;
  }

}

Jelas menimpa layanan inti memiliki beberapa risiko, tetapi itu keren bahwa Anda dapat melakukan ini.

Apa risiko mengungguli layanan inti?

1) Anda dapat kehilangan manfaat dari pembaruan saat Anda memperbarui inti. Jika ada perbaikan keamanan penting dalam layanan, dan salinan Anda yang diubah memiliki celah keamanan, Anda tidak akan mendapat manfaat dari komunitas yang memperbarui kode itu.

2) Modul lain yang Anda instal mungkin memiliki dependensi ke layanan asli dengan set fitur aslinya. Jadi misalkan ada beberapa kode dalam modul lain yang akan rusak jika jumlah entri autocomplete lebih besar dari atau kurang dari 10, Anda tidak akan mengetahuinya, sampai itu memengaruhi Anda.

3) Ini membuat basis kode Anda lebih sulit untuk dipelihara. Anda harus ingat bahwa Anda tidak menggunakan Drupal inti, tetapi versi yang diperpanjang. Pengembang lain yang bergabung dengan proyek Anda setelah Anda pergi mungkin mengalami kesulitan mencari tahu mengapa suatu layanan berperilaku dengan cara yang tidak standar.

Apakah ini inti peretasan?

Tergantung bagaimana Anda melihatnya. Itu tidak masuk ke modul inti dan mengubah kode. Bahkan tidak membuat tambalan dan menerapkannya dan melacaknya dengan manajer paket seperti komposer. Ini lebih dari satu kali penyesuaian yang mengubah perilaku inti situs, mirip dengan kait ALTER. Ini lebih mandiri daripada peretasan inti, karena itu ada dalam modul khusus Anda di situs Anda. Jadi, pembaruan inti ke layanan asli tidak akan terpengaruh, sama seperti jika Anda menambal atau meretas kode layanan asli.

Tetapi memang memiliki beberapa risiko yang sama dengan inti peretasan, seperti yang disebutkan di atas.

Dalam pertanyaan asli, masalah adalah judul node tidak cukup unik. Solusi yang lebih baik, selain mengubah batas drop-down secara global akan menyelesaikan masalah keunikan.

Apa yang saya sarankan adalah menambahkan field_display_title bidang baru dan menggunakannya pada halaman, dan jika Anda membutuhkannya field_teaser_title untuk ditampilkan pada halaman daftar di mana Anda memerlukan judul yang lebih pendek. Maka judul sebenarnya yang akan ditarik ke dropdown pilih referensi entitas dapat bermanfaat bagi editor Anda dan menjadi unik, seperti "Artikel Saya (halaman 1)" jika masalahnya adalah setiap halaman memiliki judul yang sama. Maka Anda tidak perlu mengganti layanan inti.

Ketika Anda menemukan masalah dengan Drupal, cobalah untuk menemukan solusi yang membutuhkan kode kustom paling sedikit. Ini membuat situs Anda lebih stabil, lebih mudah untuk memelihara dan menghemat waktu Anda.

oknate
sumber
3
Pada dasarnya mengesampingkan layanan inti memiliki implikasi yang sama dengan menerapkan kait ALTER. Risiko terjadi tetapi mereka sangat kecil dan dapat dikurangi dengan dokumentasi kode yang tepat.
ya.teck
1
Karena sejumlah besar penggantian, pengait, tambalan dapat mengurangi pemeliharaan proyek.
ya.teck
Bagi saya ini seperti kasus penggunaan yang sempurna untuk [penghias layanan] ( blueoakinteractive.com/blog/service-decorators-drupal-8 ).
Beau
7

Saya kira mengesampingkan EntityAutocompleteMatcher akan memengaruhi semua elemen formulir autocomplete di situs Anda. Jadi saya akan membuat plugin pemilihan entitas baru karena itu pendekatan yang lebih rinci. Plugin dapat diaktifkan per bidang. Ini adalah contoh dari plugin semacam itu. https://drupal.stackexchange.com/a/220136/433

Dalam kasus Anda, implementasi akan lebih sepele:

File: modules / example / src / Plugin / EntityReferenceSelection / ExampleSelection.php

namespace Drupal\example\Plugin\EntityReferenceSelection;

use Drupal\node\Plugin\EntityReferenceSelection\NodeSelection;

/**
 * Entity reference selection.
 *
 * @EntityReferenceSelection(
 *   id = "example:node",
 *   label = @Translation("Example node"),
 *   group = "example",
 * )
 */
class ExampleSelection extends NodeSelection {

  /**
   * {@inheritdoc}
   */
  public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
   return parent::getReferenceableEntities($match, $match_operator, 25);
  }

}

Menggunakan NodeSelection sebagai kelas dasar alih-alih DefaultSelection akan memungkinkan Anda untuk memfilter node yang direferensikan berdasarkan statusnya. Perhatikan bahwa referensi tipe entitas lainnya belum didukung .

Tidak seperti widget tautan referensi entitas tidak memungkinkan untuk menentukan plugin pemilihan melalui antarmuka pengguna, karena itu Anda perlu mengaturnya secara terprogram menggunakan hook_field_widget_WIDGET_TYPE_form_alter () .

/**
 * Implements hook_field_widget_WIDGET_TYPE_form_alter().
 */
function example_field_widget_link_default_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
  // Replace default selection handler to increase limit of displayed entities.
  $element['uri']['#selection_handler'] = 'example:node';
}

Adalah penting bahwa ID plugin berisi tanda titik koma.

ya.teck
sumber
4

Cara mudah lain untuk memodifikasi jumlah hasil adalah mengubah nilai rentang dalam kueri:

/**
 * Implements hook_query_TAG_alter() for entity reference selection handlers.
 *
 * We like tho show always 30 results instead of the 10 definied in EntityAutocompleteMatcher::getMatches()
 */
function MODULE_query_entity_reference_alter(AlterableInterface $query) {
  $query->range(0, 30);
}
Weri
sumber
1

@Weri, saya akan menghindari melakukan itu, karena baru saja menerapkan saran Anda dan menghabiskan sebagian besar hari berusaha memperbaiki masalah lain.

Perubahan kueri yang Anda sarankan juga memengaruhi keseluruhan referensi saat menautkan paragraf ke node. Node yang saya bangun memiliki 80+ item paragraf sebelum saya menambahkan alter. Setelah ditambahkan, saya tidak dapat menyimpan simpul. Menghapus / Mengomentari alter memperbaiki masalah.

Memperbarui

Membungkus $ query-> range () dalam pemeriksaan rute memperbaiki masalah bagi saya, misalnya,

function mymodule_query_entity_reference_alter($query) {
  $routeMatch = \Drupal::routeMatch();
  if ($routeMatch->getRouteName() == 'system.entity_autocomplete') {
    $query->range(0, 20);
  }
}
Richard
sumber
0

FWIW, Anda bisa mengatur tampilan formulir bidang menjadi "Pilih Daftar" daripada "Pelengkapan Otomatis".

Kemudian, Anda akan mendapatkan semua opsi, meskipun dalam format yang kurang nyaman, tetapi tidak diperlukan peretasan.

ognockocaten
sumber