Bağlantı widget'ı otomatik tamamlamasında 10'dan fazla öğe nasıl görüntülenir?


10

Bu Link modülü hakkında bir soru. Link modülü ile hem harici hem de dahili linkleri girebileceğiniz için, buna kesinlikle güveniyoruz.

Maalesef, otomatik tamamlama alanında görüntülenecek öğe sayısı 10 ile sınırlıdır. Neredeyse aynı başlıklara sahip çok sayıda düğümümüz var ve bu nedenle aradığımız düğüm otomatik tamamlama alanında görüntülenmiyor 10'dan fazla eşleşen başlık.

Sınır sabit olarak kodlanmıştır core/lib/Drupal/Core/Entity/EntityAutocompleteMatcher.php. Bu küçük sayıyı özel bir modülün içinden arttırmanın zarif bir yolu var mı? Uzatmam gerekiyor class EntityAutocompleteMatchermu? Uzantımı nereye yerleştirmem ve bağlantı widget'ından yürütülmesini nasıl sağlayabilirim?

Yanıtlar:



10

Tüm otomatik tamamlama sınırlarını geçersiz kılarak yaşayabiliyorsanız , Drupal 8'de bir temel hizmeti geçersiz kılabilirsiniz ;

Geçersiz kılmanız gereken hizmet burada core.services.yml dosyasında bulunur:

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

Özel modülünüze ServiceModifierInterface uygulayan bir sınıf ekleyin

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);
  }

}

Ardından EntityAutocompleteMatcher.php dosyasını /src/Entity/EntityAutocompleteMatcherCustom.php adresindeki modülünüze kopyalayın.

Ardından sabit kodlanmış 10'u 50'ye veya istediğiniz herhangi bir sınıra güncelleyin:

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;
  }

}

Açıkçası, temel hizmetlerin geçersiz kılınmasının bazı riskleri vardır, ancak bunu yapabilmeniz harika.

Temel bir hizmeti geçersiz kılma riskleri nelerdir?

1) Çekirdeği güncellediğinizde güncellemelerin avantajlarını kaybedebilirsiniz. Hizmette kritik bir güvenlik düzeltmesi varsa ve değiştirilmiş kopyanızın güvenlik açığı varsa, bu kodu güncelleyen topluluktan yararlanamazsınız.

2) Taktığınız diğer modüller, orijinal özellik setiyle orijinal hizmete bağımlı olabilir. Diyelim ki, otomatik tamamlama girişlerinin sayısı 10'dan fazla veya daha azsa, başka bir modülde kırılacak bazı kodlar var, sizi etkileyene kadar bunu bilmeyeceksiniz.

3) Kod tabanınızın bakımını zorlaştırır. Çekirdek Drupal'ı değil, genişletilmiş bir sürümünü kullandığınızı hatırlamanız gerekir. Ayrıldıktan sonra projenize katılan diğer geliştiriciler, bir hizmetin neden standart dışı bir şekilde davrandığını anlamakta zorlanabilirler.

Bu korsanlık çekirdeği mi?

Ona nasıl baktığına bağlı. Çekirdek modüle girmiyor ve kodu değiştirmiyor. Bir yama oluşturmak ve uygulamak ve besteci gibi bir paket yöneticisi ile izlemek bile değildir. Bir ALTER kancasına benzer şekilde, sitelerin temel davranışını değiştiren tek seferlik bir özelleştirmeden daha fazlasıdır. Bir çekirdek kesmek daha bağımsızdır, çünkü sitenizdeki kendi özel modülünüzdedir. Bu nedenle, orijinal hizmet kodunda yapılan temel güncellemeler, orijinal hizmet kodunu yamaladığınız veya hacklediğiniz gibi etkilenmez.

Ancak, yukarıda belirtildiği gibi, korsanlık çekirdeği ile aynı risklerden bazılarına sahiptir.

Orijinal soruda, sorun düğüm başlıkları yeterince benzersiz değildi. Açılır kapanışlarda küresel olarak limiti değiştirmek dışında daha iyi bir çözüm, teklik sorununu çözmek olacaktır.

Ne öneririm yeni bir alan field_display_title eklemek ve bunu sayfada kullanmak ve gerekirse başka bir alan field_teaser_title daha kısa bir başlık gereken liste sayfalarında görüntülemek için. Daha sonra varlık referansı seçme açılır menüsüne çekilen gerçek başlık, düzenleyicileriniz için yararlı olabilir ve her sayfada aynı başlık varsa "Makalem (sayfa 1)" gibi benzersiz olabilir. O zaman bir çekirdek hizmeti geçersiz kılmak zorunda kalmazsınız.

Drupal ile ilgili bir sorunla karşılaştığınızda, en az miktarda özel kod gerektiren çözümü bulmaya çalışın. Bu, sitenizi daha kararlı, bakımı daha kolay hale getirir ve size zaman kazandırır.


3
Temel olarak bir çekirdek hizmetin geçersiz kılınması, ALTER kancalarının uygulanmasıyla aynı sonuçlara sahiptir. Riskler meydana gelir, ancak bunlar oldukça küçüktür ve uygun kod belgeleri ile hafifletilebilir.
ya.teck

1
Bu tür geçersiz kılmaların, kancaların, yamaların çok sayıda olması projenin sürdürülebilirliğini azaltabilir.
ya.teck

Bu bana bir [servis dekoratörü] ( blueoakinteractive.com/blog/service-decorators-drupal-8 ) için mükemmel bir kullanım durumu gibi geliyor .
Beau

7

EntityAutocompleteMatcher'ın geçersiz kılınmasının sitenizdeki tüm otomatik tamamlama form öğelerini etkileyeceğini düşünüyorum. Böylece daha ayrıntılı bir yaklaşım olduğu için yeni bir varlık seçimi eklentisi oluşturacağım. Eklenti alan başına etkinleştirilebilir. İşte böyle bir eklentiye bir örnek. https://drupal.stackexchange.com/a/220136/433

Sizin durumunuzda uygulama daha da önemsiz olacaktır:

Dosya: modülleri / örnek / src / Eklenti / EntityReferenceSelection / ÖrnekSelection.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);
  }

}

Kullanılması NodeSelection yerine DefaultSelection taban sınıf olarak kendi durumuna göre başvurulan düğümleri filtrelemek için izin verecek. Diğer varlık türlerine başvurmanın henüz desteklenmediğini unutmayın .

Varlık referans bağlantı widget'ının aksine, kullanıcı arabirimi aracılığıyla seçim eklentisi belirtmeye izin vermez, bu nedenle bunu hook_field_widget_WIDGET_TYPE_form_alter () kullanarak programlı olarak ayarlamanız gerekir .

/**
 * 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';
}

Eklenti kimliğinin noktalı virgül içermesi önemlidir.


4

Sonuç sayısını değiştirmenin diğer bir kolay yolu, sorgudaki aralık değerini değiştirmektir:

/**
 * 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);
}

1

@Weri, bunu yapmaktan kaçınırdım, sadece önerinizi uyguladım ve günün en iyi kısmını başka bir sorunu düzeltmeye çalışarak geçirdim.

Önerdiğiniz sorgu değişikliği, paragrafları düğümlere bağlarken giriş referansını da etkiler. Uyandığım bir düğümü değiştirmeden önce 80'den fazla paragraf öğesi vardı. Eklendikten sonra düğümü kaydedemedim. Değişikliğin kaldırılması / yorumlanması sorunu çözdü.

Güncelleme

$ Query-> range () yöntemini bir rota kontrolünde silmek benim için sorunu çözer, örnek,

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

0

FWIW, alanın form görüntüsünü "Otomatik Tamamla" yerine "Liste Seç" olarak ayarlayabilirsiniz.

Ardından, daha az uygun bir formatta da olsa, tüm seçenekleri elde edersiniz, ancak kesmek gerekmez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.