लिंक विजेट स्वतः पूर्ण में 10 से अधिक आइटम कैसे प्रदर्शित करें?


10

यह लिंक मॉड्यूल के बारे में एक प्रश्न है। चूंकि लिंक मॉड्यूल के साथ आप बाहरी या आंतरिक लिंक दोनों में प्रवेश कर सकते हैं, हम दृढ़ता से इस पर भरोसा करते हैं।

दुर्भाग्य से इसके स्व-पूर्ण क्षेत्र से प्रदर्शित होने वाली वस्तुओं की संख्या 10. तक सीमित है। हमारे पास लगभग समान खिताबों के साथ बहुत सारे नोड हैं और इसलिए यह आता है कि हम जिस नोड की खोज कर रहे हैं वह स्वत: पूर्ण फ़ील्ड में प्रदर्शित नहीं होता है जब वहाँ होते हैं 10 से अधिक मिलान शीर्षक।

में सीमा हार्डकोड है core/lib/Drupal/Core/Entity/EntityAutocompleteMatcher.php। क्या कस्टम मॉड्यूल के भीतर से इस छोटी संख्या को बढ़ाने का एक सुंदर तरीका है? क्या मुझे विस्तार करना है class EntityAutocompleteMatcher? मुझे अपना एक्सटेंशन कहां रखना होगा और यह सुनिश्चित करना होगा कि इसे लिंक विजेट के भीतर से कैसे निष्पादित किया जाए?

जवाबों:



10

यदि आप सभी स्वत: पूर्ण सीमाओं को ओवरराइड करने के साथ रह सकते हैं, तो आप Drupal 8 में एक कोर सेवा को ओवरराइड कर सकते हैं ;

जिस सेवा को आपको ओवरराइड करने की आवश्यकता है वह यहाँ core.services.yml में है:

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

अपने कस्टम मॉड्यूल में, एक वर्ग जोड़ें जो 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);
  }

}

फिर EntityAutocompleteMatcher.php को अपने मॉड्यूल में /src/Entity/EntityAutocompleteMatcherCustom.php पर कॉपी करें

फिर हार्डकोड 10 से 50 तक अपडेट करें, या जो भी सीमा आप चाहें:

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

}

स्पष्ट रूप से मुख्य सेवाओं में ओवरराइड के कुछ जोखिम हैं, लेकिन यह अच्छा है कि आप ऐसा कर सकते हैं।

एक कोर सेवा को ओवरराइड करने के जोखिम क्या हैं?

1) जब आप कोर अपडेट करते हैं तो आप अपडेट के लाभ खो सकते हैं। यदि सेवा में कोई महत्वपूर्ण सुरक्षा फ़िक्स है, और आपकी परिवर्तित प्रति में सुरक्षा छेद है, तो आपको उस कोड को अपडेट करने वाले समुदाय से लाभ नहीं होगा।

2) आपके द्वारा इंस्टॉल किए गए अन्य मॉड्यूल में मूल सेवा सेट के साथ मूल सेवा के लिए निर्भरताएं हो सकती हैं। तो मान लें कि किसी अन्य मॉड्यूल में कुछ कोड है जो टूट जाएगा यदि स्वतः पूर्ण प्रविष्टियों की संख्या 10 से अधिक या उससे कम है, तो आपको इसके बारे में पता नहीं चलेगा, जब तक कि यह आपको प्रभावित नहीं करता।

3) यह आपके कोडबेस को बनाए रखने के लिए कठिन बनाता है। आपको यह याद रखना होगा कि आप कोर ड्रुपल का उपयोग नहीं कर रहे हैं, बल्कि एक विस्तारित संस्करण है। अन्य डेवलपर्स जो आपके जाने के बाद आपकी परियोजना में शामिल होते हैं, उन्हें यह पता लगाने में मुश्किल समय हो सकता है कि कोई सेवा गैर-मानक तरीके से व्यवहार क्यों कर रही है।

क्या यह हैकिंग कोर है?

निर्भर करता है कि आप इसे कैसे देखते हैं। यह कोर मॉड्यूल और बदलते कोड में नहीं जा रहा है। यह एक पैच भी नहीं बना रहा है और इसे लागू कर रहा है और संगीतकार जैसे पैकेज मैनेजर के साथ इसे ट्रैक कर रहा है। यह एक एकल-बंद अनुकूलन से अधिक है जो एक साइट के मूल व्यवहार को बदल देता है, जो एक ALTER हुक के समान है। यह अधिक आत्म-निहित है कि एक कोर हैक, क्योंकि यह आपकी साइट पर अपने स्वयं के कस्टम मॉड्यूल के भीतर है। तो मूल सेवा के लिए कोर अपडेट प्रभावित नहीं होगा, उसी तरह जैसे कि आपने मूल सेवा कोड को पैच या हैक किया था।

लेकिन इसमें हैकिंग कोर के समान कुछ जोखिम हैं, जैसा कि ऊपर बताया गया है।

मूल प्रश्न में, मुद्दा यह था कि नोड टाइटल्स अद्वितीय नहीं हैं। ड्रॉप डाउन पर विश्व स्तर पर सीमा को बदलने के अलावा, बेहतर समाधान, विशिष्टता समस्या का समाधान होगा।

मेरा सुझाव है कि एक नया फ़ील्ड field_display_title जोड़ना और पृष्ठ पर उस का उपयोग करना है, और यदि आपको सूची पृष्ठों पर प्रदर्शन के लिए किसी अन्य फ़ील्ड field_teaser_title की आवश्यकता है, जहां आपको एक छोटे शीर्षक की आवश्यकता है। तब वास्तविक शीर्षक जो इकाई संदर्भ में चयनित हो जाता है ड्रॉपडाउन आपके संपादकों के लिए उपयोगी हो सकता है और अद्वितीय हो सकता है, जैसे कि "मेरा आलेख (पृष्ठ 1)" यदि समस्या प्रत्येक पृष्ठ का समान शीर्षक है। फिर आपको एक कोर सेवा को ओवरराइड नहीं करना है।

जब आप ड्रुपल के साथ कोई समस्या लेते हैं, तो उस समाधान को खोजने का प्रयास करें जिसके लिए कम से कम कस्टम कोड की आवश्यकता होती है। यह आपकी साइट को और अधिक स्थिर, आसान बनाए रखता है और आपको समय बचाता है।


3
मूल रूप से एक मूल सेवा को ओवरराइड करने का एक ही अर्थ है कि ALTER हुक को लागू करना। जोखिम होते हैं, लेकिन वे काफी मामूली होते हैं और उचित कोड प्रलेखन के साथ कम किए जा सकते हैं।
येटेक

1
इस तरह के ओवरराइड, हुक, पैच की एक अच्छी संख्या के कारण परियोजना की स्थिरता कम हो सकती है।
ya.teck

यह मुझे [सर्विस डेकोरेटर] ( blueoakinteractive.com/blog/service-decorators-drupal-8 ) के लिए एक सही उपयोग के मामले की तरह लगता है ।
ब्यू

7

मुझे लगता है कि EntityAutocompleteMatcher को ओवरराइड करने से आपकी साइट पर सभी स्वतः पूर्ण फ़ॉर्म तत्व प्रभावित होंगे। ताकि मैं इसके बजाय एक नई इकाई चयन प्लगइन बनाऊं क्योंकि यह अधिक बारीक दृष्टिकोण है। प्लगइन प्रति क्षेत्र में सक्षम किया जा सकता है। यहाँ इस तरह के एक प्लगइन का एक उदाहरण है। https://drupal.stackexchange.com/a/220136/433

आपके मामले में कार्यान्वयन और भी अधिक तुच्छ होगा:

फ़ाइल: मॉड्यूल / उदाहरण / src / प्लगइन / 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);
  }

}

DefaultSelection के बजाय बेस क्लास के रूप में NodeSelection का उपयोग करने से आप उनकी स्थिति से संदर्भित नोड फ़िल्टर कर सकते हैं। ध्यान दें कि अन्य इकाई प्रकारों को संदर्भित करना अभी तक समर्थित नहीं है।

निकाय संदर्भ लिंक के विपरीत विजेट यूजर इंटरफेस के माध्यम से चयन प्लगइन को निर्दिष्ट करने की अनुमति नहीं देता है, इसलिए आपको हुक_फ़ील्ड_विद्या_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';
}

यह महत्वपूर्ण है कि प्लगइन आईडी में अर्धविराम शामिल है।


4

परिणामों की संख्या को संशोधित करने का एक अन्य आसान तरीका क्वेरी में श्रेणी मान को बदलना है:

/**
 * 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, मैं ऐसा करने से बचता हूँ, जिसने आपके सुझाव पर अमल किया और एक दिन का सबसे अच्छा हिस्सा दूसरे मुद्दे को ठीक करने में लगा दिया।

आपके द्वारा सुझाए गए क्वेरी परिवर्तन, पैराग्राफ को नोड्स से लिंक करते समय भी अस्पष्ट संदर्भ को प्रभावित करता है। एक नोड जिसे मैं बदल रहा था इससे पहले कि मैं परिवर्तन जोड़ रहा था मैं 80+ पैराग्राफ आइटम पर जा रहा था। एक बार जोड़ने के बाद मैं नोड को बचाने में असमर्थ था। हटाने / टिप्पणी को बदलने से समस्या तय हो गई।

अपडेट करें

मार्ग जांच में $ क्वेरी-> रेंज () को लपेटकर मेरे लिए समस्या को हल करता है, उदाहरण के लिए,

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

0

FWIW, आप केवल "स्वतः पूर्ण" के बजाय फ़ील्ड के प्रदर्शन को "चयन सूची" में सेट कर सकते हैं।

फिर, आपको कम सुविधाजनक प्रारूप में सभी विकल्प मिलेंगे, लेकिन हैक की आवश्यकता नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.