Score:1

How to override a class method that is not a service?

ธง lb

Usually we override services using RouteSubscribers, but i need to override a method of a class that is not a service. I need to alter the module of the core "views", the general structure of this module is:

> views
  > src
    > Entity
      > Render
        - ConfigurableLanguageRenderer.php
        - EntityTranslationRenderTrait.php

I need to override one method of one of those files.

In ConfigurableLanguageRenderer.php i need to override "getLanguage()" method or in EntityTranslationRenderTrait.php i need to override "getEntityTranslation()" method, but i don't know how override a trait or a class that is not a service, is that possible? Thanks.

--- More context ---

A hook_language_fallback_candidates_OPERATION_alter() was implemented and we have a custom priority candidates to return the content translated, but one validation in the views module broke my custom fallback candidates.

E.G: if the content was written in English(en), and you send in the view rest the parameter lang=en, the view will be skip to search the translation in the candidates and the hook_language_fallback... doesn't be executed because if you looking for a node in english and this article has english as default is not necessary to search translation and this return the original language of the content.

Then i need to alter the langcode that return $this->getEntityTranslationRenderer()->getLangcode($row)

  • ConfigurableLanguageRenderer.php

    public function getEntityTranslation(EntityInterface $entity, ResultRow $row) {
      // We assume the same language should be used for all entity fields
      // belonging to a single row, even if they are attached to different entity
      // types. Below we apply language fallback to ensure a valid value is always
      // picked.
      $translation = $entity;
      if ($entity instanceof TranslatableInterface && count($entity->getTranslationLanguages()) > 1) {
        $langcode = $this->getEntityTranslationRenderer()->getLangcode($row);
        $translation = $this->getEntityRepository()->getTranslationFromContext($entity, $langcode);
      }
      return $translation;
    }
    

So i need to alter those methods or alter the default language of the node, or if it's possible alter "context" to enter to the following validation: ($entity->language()->getId() != $langcode)

public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = []) {
    $translation = $entity;

    if ($entity instanceof TranslatableDataInterface && count($entity->getTranslationLanguages()) > 1) {
      if (empty($langcode)) {
        $langcode = $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
        $entity->addCacheContexts(['languages:' . LanguageInterface::TYPE_CONTENT]);
      }

      // Retrieve language fallback candidates to perform the entity language
      // negotiation, unless the current translation is already the desired one.
      if ($entity->language()->getId() != $langcode) {
        $context['data'] = $entity;
        $context += ['operation' => 'entity_view', 'langcode' => $langcode];
        $candidates = $this->languageManager->getFallbackCandidates($context);

        // Ensure the default language has the proper language code.
        $default_language = $entity->getUntranslated()->language();
        $candidates[$default_language->getId()] = LanguageInterface::LANGCODE_DEFAULT;

        // Return the most fitting entity translation.
        foreach ($candidates as $candidate) {
          if ($entity->hasTranslation($candidate)) {
            $translation = $entity->getTranslation($candidate);
            break;
          }
        }
      }
    }

    return $translation;
  }

-- Update --

as @4k4 mentioned i overwritten the service EntityRepository.php and that solved my problem

class GlobalizationServiceProvider extends ServiceProviderBase {

  /**
  * {@inheritdoc}
  */
  public function alter(ContainerBuilder $container) {
    if ($container->hasDefinition('entity.repository')) {
      $definition = $container->getDefinition('entity.repository');
      $definition->setClass('Drupal\Globalization\CustomEntityRepository');
    }
  }
}
in flag
คุณอาจต้องการให้บริบทเล็กน้อยเกี่ยวกับสิ่งที่คุณพยายามบรรลุ อาจมีวิธีอื่นในการบรรลุสิ่งที่คุณพยายามทำนอกเหนือจากวิธีนี้
Score:1
ธง cn

คลาสแรกเป็นฮาร์ดโค้ดในคลาสที่สอง และคลาสที่สองเป็นลักษณะที่ใช้ในปลั๊กอินฟิลด์และแถวต่างๆ ดังนั้นคุณต้องกำหนดเป้าหมายหนึ่งในปลั๊กอินเหล่านั้น มีหลายวิธี สิ่งที่ต้องการคือการกำหนด ID ปลั๊กอินที่กำหนดเองให้กับคลาสปลั๊กอินเสริมและกำหนดค่าในมุมมองที่กำหนดเองของคุณ หากคุณต้องการแทนที่คลาสปลั๊กอินโดยทั่วไปโปรดดู ฉันจะเปลี่ยนปลั๊กอินได้อย่างไร


วิธีสุดท้ายที่คุณเพิ่มเข้ามา บริบทมากขึ้น อยู่ในบริการและคุณสามารถนำไปใช้ได้ MyEntityRepository::getTranslationFromContext() จากนั้นสลับคลาสใน ServiceProvider (ไม่ใช่ RouteSubcriber): ดู การเปลี่ยนแปลงบริการที่มีอยู่.

Mauricio avatar
lb flag
ในฐานะ @ 4k4 นั่นคือวิธีแก้ปัญหาของฉัน ขอบคุณ

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา