Điểm:1

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

lá cờ 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');
    }
  }
}
lá cờ in
Bạn có thể muốn cung cấp một chút bối cảnh về những gì bạn đang cố gắng đạt được. Có thể có những cách khác để đạt được những gì bạn đang cố gắng thực hiện ngoài cách tiếp cận này.
Điểm:1
lá cờ cn

Lớp đầu tiên được mã hóa cứng trong lớp thứ hai và lớp thứ hai là một đặc điểm được sử dụng trong các plugin trường và hàng khác nhau. Vì vậy, bạn cần nhắm mục tiêu một trong những plugin đó. Có một số cách. Cách ưu tiên là chỉ định ID plugin tùy chỉnh cho lớp plugin mở rộng và định cấu hình nó trong Chế độ xem tùy chỉnh của bạn. Nếu bạn muốn ghi đè lớp plugin nói chung, hãy xem Làm cách nào để thay thế plugin?


Phương pháp cuối cùng bạn đã thêm vào thêm ngữ cảnh đang ở trong một dịch vụ và bạn có thể thực hiện MyEntityRepository::getTranslationFromContext() và sau đó hoán đổi lớp trong ServiceProvider (không phải RouteSubcriber): Xem thay đổi các dịch vụ hiện có.

Mauricio avatar
lá cờ lb
@4k4 đó là giải pháp cho vấn đề của tôi, cảm ơn

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.