Рейтинг: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
Возможно, вы захотите предоставить немного контекста относительно того, чего вы пытаетесь достичь. Могут быть другие способы добиться того, что вы пытаетесь сделать, чем этот подход.
Рейтинг:1
флаг cn

Первый класс жестко запрограммирован во втором классе, а второй класс является чертой, используемой в различных плагинах полей и строк. Поэтому вам нужно настроить таргетинг на один из этих плагинов. Есть несколько способов. Предпочтительным является назначение пользовательского идентификатора плагина расширенному классу плагина и настройка его в вашем пользовательском представлении. Если вы хотите переопределить класс плагина в целом, см. Как заменить плагин?


Последний метод, который вы добавили в больше контекста находится в службе, и вы можете реализовать MyEntityRepository::getTranslationFromContext() а затем поменяйте класс в ServiceProvider (не RouteSubscriber): см. изменение существующих услуг.

Mauricio avatar
флаг lb
как @4k4, это было решением моей проблемы, спасибо

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.