You are here

class RenderedItem in Search API 8

Adds an additional field containing the rendered item.

Plugin annotation


@SearchApiProcessor(
  id = "rendered_item",
  label = @Translation("Rendered item"),
  description = @Translation("Adds an additional field containing the rendered item as it would look when viewed."),
  stages = {
    "add_properties" = 0,
  },
  locked = true,
  hidden = true,
)

Hierarchy

Expanded class hierarchy of RenderedItem

See also

\Drupal\search_api\Plugin\search_api\processor\Property\RenderedItemProperty

File

src/Plugin/search_api/processor/RenderedItem.php, line 37

Namespace

Drupal\search_api\Plugin\search_api\processor
View source
class RenderedItem extends ProcessorPluginBase {
  use LoggerTrait;

  /**
   * The current_user service used by this plugin.
   *
   * @var \Drupal\Core\Session\AccountSwitcherInterface|null
   */
  protected $accountSwitcher;

  /**
   * The renderer to use.
   *
   * @var \Drupal\Core\Render\RendererInterface|null
   */
  protected $renderer;

  /**
   * Theme manager service.
   *
   * @var \Drupal\Core\Theme\ThemeManagerInterface
   */
  protected $themeManager;

  /**
   * Theme initialization service.
   *
   * @var \Drupal\Core\Theme\ThemeInitializationInterface
   */
  protected $themeInitialization;

  /**
   * Theme settings config.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {

    /** @var static $plugin */
    $plugin = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $plugin
      ->setAccountSwitcher($container
      ->get('account_switcher'));
    $plugin
      ->setRenderer($container
      ->get('renderer'));
    $plugin
      ->setLogger($container
      ->get('logger.channel.search_api'));
    $plugin
      ->setThemeManager($container
      ->get('theme.manager'));
    $plugin
      ->setThemeInitializer($container
      ->get('theme.initialization'));
    $plugin
      ->setConfigFactory($container
      ->get('config.factory'));
    return $plugin;
  }

  /**
   * Retrieves the account switcher service.
   *
   * @return \Drupal\Core\Session\AccountSwitcherInterface
   *   The account switcher service.
   */
  public function getAccountSwitcher() {
    return $this->accountSwitcher ?: \Drupal::service('account_switcher');
  }

  /**
   * Sets the account switcher service.
   *
   * @param \Drupal\Core\Session\AccountSwitcherInterface $current_user
   *   The account switcher service.
   *
   * @return $this
   */
  public function setAccountSwitcher(AccountSwitcherInterface $current_user) {
    $this->accountSwitcher = $current_user;
    return $this;
  }

  /**
   * Retrieves the renderer.
   *
   * @return \Drupal\Core\Render\RendererInterface
   *   The renderer.
   */
  public function getRenderer() {
    return $this->renderer ?: \Drupal::service('renderer');
  }

  /**
   * Sets the renderer.
   *
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The new renderer.
   *
   * @return $this
   */
  public function setRenderer(RendererInterface $renderer) {
    $this->renderer = $renderer;
    return $this;
  }

  /**
   * Retrieves the theme manager.
   *
   * @return \Drupal\Core\Theme\ThemeManagerInterface
   *   The theme manager.
   */
  protected function getThemeManager() {
    return $this->themeManager ?: \Drupal::theme();
  }

  /**
   * Sets the theme manager.
   *
   * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
   *   The theme manager.
   *
   * @return $this
   */
  protected function setThemeManager(ThemeManagerInterface $theme_manager) {
    $this->themeManager = $theme_manager;
    return $this;
  }

  /**
   * Retrieves the theme initialization service.
   *
   * @return \Drupal\Core\Theme\ThemeInitializationInterface
   *   The theme initialization service.
   */
  protected function getThemeInitializer() {
    return $this->themeInitialization ?: \Drupal::service('theme.initialization');
  }

  /**
   * Sets the theme initialization service.
   *
   * @param \Drupal\Core\Theme\ThemeInitializationInterface $theme_initialization
   *   The theme initialization service.
   *
   * @return $this
   */
  protected function setThemeInitializer(ThemeInitializationInterface $theme_initialization) {
    $this->themeInitialization = $theme_initialization;
    return $this;
  }

  /**
   * Retrieves the config factory service.
   *
   * @return \Drupal\Core\Config\ConfigFactoryInterface
   *   The config factory.
   */
  protected function getConfigFactory() {
    return $this->configFactory ?: \Drupal::configFactory();
  }

  /**
   * Sets the config factory service.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   *
   * @return $this
   */
  protected function setConfigFactory(ConfigFactoryInterface $config_factory) {
    $this->configFactory = $config_factory;
    return $this;
  }

  // @todo Add a supportsIndex() implementation that checks whether there is
  //   actually any datasource present which supports viewing.

  /**
   * {@inheritdoc}
   */
  public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) {
    $properties = [];
    if (!$datasource) {
      $definition = [
        'label' => $this
          ->t('Rendered HTML output'),
        'description' => $this
          ->t('The complete HTML which would be displayed when viewing the item'),
        'type' => 'search_api_html',
        'processor_id' => $this
          ->getPluginId(),
      ];
      $properties['rendered_item'] = new RenderedItemProperty($definition);
    }
    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public function addFieldValues(ItemInterface $item) {

    // Switch to the default theme in case the admin theme is enabled.
    $active_theme = $this
      ->getThemeManager()
      ->getActiveTheme();
    $default_theme = $this
      ->getConfigFactory()
      ->get('system.theme')
      ->get('default');
    $default_theme = $this
      ->getThemeInitializer()
      ->getActiveThemeByName($default_theme);
    $this
      ->getThemeManager()
      ->setActiveTheme($default_theme);

    // Fields for which some view mode config is missing.
    $unset_view_modes = [];
    $fields = $this
      ->getFieldsHelper()
      ->filterForPropertyPath($item
      ->getFields(), NULL, 'rendered_item');
    foreach ($fields as $field) {
      $configuration = $field
        ->getConfiguration();

      // Change the current user to our dummy implementation to ensure we are
      // using the configured roles.
      $this
        ->getAccountSwitcher()
        ->switchTo(new UserSession([
        'roles' => $configuration['roles'],
      ]));
      $datasource_id = $item
        ->getDatasourceId();
      $datasource = $item
        ->getDatasource();
      $bundle = $datasource
        ->getItemBundle($item
        ->getOriginalObject());

      // When no view mode has been set for the bundle, or it has been set to
      // "Don't include the rendered item", skip this item.
      if (empty($configuration['view_mode'][$datasource_id][$bundle])) {

        // If it was really not set, also notify the user through the log.
        if (!isset($configuration['view_mode'][$datasource_id][$bundle])) {
          $unset_view_modes[$field
            ->getFieldIdentifier()] = $field
            ->getLabel();
        }
        continue;
      }
      $view_mode = (string) $configuration['view_mode'][$datasource_id][$bundle];
      try {
        $build = $datasource
          ->viewItem($item
          ->getOriginalObject(), $view_mode);
        if ($build) {

          // Add the excerpt to the render array to allow adding it to view modes.
          $build['#search_api_excerpt'] = $item
            ->getExcerpt();
          $value = (string) $this
            ->getRenderer()
            ->renderPlain($build);
          if ($value) {
            $field
              ->addValue($value);
          }
        }
      } catch (\Exception $e) {

        // This could throw all kinds of exceptions in specific scenarios, so we
        // just catch all of them here. Not having a field value for this field
        // probably makes sense in that case, so we just log an error and
        // continue.
        $variables = [
          '%item_id' => $item
            ->getId(),
          '%view_mode' => $view_mode,
          '%index' => $this->index
            ->label(),
        ];
        $this
          ->logException($e, '%type while trying to render item %item_id with view mode %view_mode for search index %index: @message in %function (line %line of %file).', $variables);
      }
    }

    // Restore the original user.
    $this
      ->getAccountSwitcher()
      ->switchBack();

    // Restore the original theme.
    $this
      ->getThemeManager()
      ->setActiveTheme($active_theme);
    if ($unset_view_modes > 0) {
      foreach ($unset_view_modes as $field_id => $field_label) {
        $url = new Url('entity.search_api_index.field_config', [
          'search_api_index' => $this->index
            ->id(),
          'field_id' => $field_id,
        ]);
        $context = [
          '%index' => $this->index
            ->label(),
          '%field_id' => $field_id,
          '%field_label' => $field_label,
          'link' => (new Link($this
            ->t('Field settings'), $url))
            ->toString(),
        ];
        $this
          ->getLogger()
          ->warning('The field %field_label (%field_id) on index %index is missing view mode configuration for some datasources or bundles. Please review (and re-save) the field settings.', $context);
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function calculateDependencies() {
    $this->dependencies = parent::calculateDependencies();
    $fields = $this
      ->getFieldsHelper()
      ->filterForPropertyPath($this->index
      ->getFields(), NULL, 'rendered_item');
    foreach ($fields as $field) {
      $view_modes = $field
        ->getConfiguration()['view_mode'];
      foreach ($this->index
        ->getDatasources() as $datasource_id => $datasource) {
        if (($entity_type_id = $datasource
          ->getEntityTypeId()) && !empty($view_modes[$datasource_id])) {
          foreach ($view_modes[$datasource_id] as $view_mode) {
            if ($view_mode) {

              /** @var \Drupal\Core\Entity\EntityViewModeInterface $view_mode_entity */
              $view_mode_entity = EntityViewMode::load($entity_type_id . '.' . $view_mode);
              if ($view_mode_entity) {
                $this
                  ->addDependency($view_mode_entity
                  ->getConfigDependencyKey(), $view_mode_entity
                  ->getConfigDependencyName());
              }
            }
          }
        }
      }
    }
    return $this->dependencies;
  }

  /**
   * {@inheritdoc}
   */
  public function onDependencyRemoval(array $dependencies) {

    // All dependencies of this processor are entity view modes, so we go
    // through all of the index's fields using our property and remove the
    // settings for all datasources or bundles which were set to one of the
    // removed view modes. This will always result in the removal of all those
    // dependencies.
    // The code is highly similar to calculateDependencies(), only that we
    // remove the setting (if necessary) instead of adding a dependency.
    $fields = $this
      ->getFieldsHelper()
      ->filterForPropertyPath($this->index
      ->getFields(), NULL, 'rendered_item');
    foreach ($fields as $field) {
      $field_config = $field
        ->getConfiguration();
      $view_modes = $field_config['view_mode'];
      foreach ($this->index
        ->getDatasources() as $datasource_id => $datasource) {
        $entity_type_id = $datasource
          ->getEntityTypeId();
        if (!$entity_type_id) {
          continue;
        }
        foreach ($view_modes[$datasource_id] ?? [] as $bundle => $view_mode_id) {
          if ($view_mode_id) {

            /** @var \Drupal\Core\Entity\EntityViewModeInterface $view_mode */
            $view_mode = EntityViewMode::load($entity_type_id . '.' . $view_mode_id);
            if ($view_mode) {
              $dependency_key = $view_mode
                ->getConfigDependencyKey();
              $dependency_name = $view_mode
                ->getConfigDependencyName();
              if (!empty($dependencies[$dependency_key][$dependency_name])) {
                unset($view_modes[$datasource_id][$bundle]);
              }
            }
          }
        }
      }
      $field_config['view_mode'] = $view_modes;
      $field
        ->setConfiguration($field_config);
    }
    return TRUE;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ConfigurablePluginBase::calculatePluginDependencies Deprecated protected function Calculates and adds dependencies of a specific plugin instance.
ConfigurablePluginBase::defaultConfiguration public function Gets default configuration for this plugin. Overrides ConfigurableInterface::defaultConfiguration 11
ConfigurablePluginBase::getConfiguration public function Gets this plugin's configuration. Overrides ConfigurableInterface::getConfiguration
ConfigurablePluginBase::getDescription public function Returns the plugin's description. Overrides ConfigurablePluginInterface::getDescription
ConfigurablePluginBase::getPluginDependencies Deprecated protected function Calculates and returns dependencies of a specific plugin instance.
ConfigurablePluginBase::label public function Returns the label for use on the administration pages. Overrides ConfigurablePluginInterface::label
ConfigurablePluginBase::moduleHandler Deprecated protected function Wraps the module handler.
ConfigurablePluginBase::setConfiguration public function Sets the configuration for this plugin instance. Overrides ConfigurableInterface::setConfiguration 3
ConfigurablePluginBase::themeHandler Deprecated protected function Wraps the theme handler.
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
DependencyTrait::$dependencies protected property The object's dependencies.
DependencyTrait::addDependencies protected function Adds multiple dependencies.
DependencyTrait::addDependency protected function Adds a dependency.
IndexPluginBase::$index protected property The index this processor is configured for.
IndexPluginBase::getIndex public function Retrieves the index this plugin is configured for. Overrides IndexPluginInterface::getIndex
IndexPluginBase::setIndex public function Sets the index this plugin is configured for. Overrides IndexPluginInterface::setIndex
IndexPluginBase::__construct public function Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides ConfigurablePluginBase::__construct 2
LoggerTrait::$logger protected property The logging channel to use.
LoggerTrait::getLogger public function Retrieves the logger.
LoggerTrait::logException protected function Logs an exception.
LoggerTrait::setLogger public function Sets the logger.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
PluginDependencyTrait::calculatePluginDependencies protected function Calculates and adds dependencies of a specific plugin instance. Aliased as: traitCalculatePluginDependencies 1
PluginDependencyTrait::getPluginDependencies protected function Calculates and returns dependencies of a specific plugin instance. Aliased as: traitGetPluginDependencies
PluginDependencyTrait::moduleHandler protected function Wraps the module handler. Aliased as: traitModuleHandler 1
PluginDependencyTrait::themeHandler protected function Wraps the theme handler. Aliased as: traitThemeHandler 1
ProcessorInterface::STAGE_ADD_PROPERTIES constant Processing stage: add properties.
ProcessorInterface::STAGE_ALTER_ITEMS constant Processing stage: alter indexed items.
ProcessorInterface::STAGE_POSTPROCESS_QUERY constant Processing stage: postprocess query.
ProcessorInterface::STAGE_PREPROCESS_INDEX constant Processing stage: preprocess index.
ProcessorInterface::STAGE_PREPROCESS_QUERY constant Processing stage: preprocess query.
ProcessorInterface::STAGE_PRE_INDEX_SAVE constant Processing stage: preprocess index.
ProcessorPluginBase::$fieldsHelper protected property The fields helper. 1
ProcessorPluginBase::alterIndexedItems public function Alter the items to be indexed. Overrides ProcessorInterface::alterIndexedItems 3
ProcessorPluginBase::ensureField protected function Ensures that a field with certain properties is indexed on the index.
ProcessorPluginBase::findField protected function Finds a certain field in the index.
ProcessorPluginBase::getFieldsHelper public function Retrieves the fields helper. 1
ProcessorPluginBase::getWeight public function Returns the weight for a specific processing stage. Overrides ProcessorInterface::getWeight
ProcessorPluginBase::isHidden public function Determines whether this plugin should be hidden in the UI. Overrides HideablePluginBase::isHidden
ProcessorPluginBase::isLocked public function Determines whether this processor should always be enabled. Overrides ProcessorInterface::isLocked
ProcessorPluginBase::postprocessSearchResults public function Postprocess search results before they are returned by the query. Overrides ProcessorInterface::postprocessSearchResults 2
ProcessorPluginBase::preIndexSave public function Preprocesses the search index entity before it is saved. Overrides ProcessorInterface::preIndexSave 5
ProcessorPluginBase::preprocessIndexItems public function Preprocesses search items for indexing. Overrides ProcessorInterface::preprocessIndexItems 5
ProcessorPluginBase::preprocessSearchQuery public function Preprocesses a search query. Overrides ProcessorInterface::preprocessSearchQuery 4
ProcessorPluginBase::requiresReindexing public function Determines whether re-indexing is required after a settings change. Overrides ProcessorInterface::requiresReindexing
ProcessorPluginBase::setFieldsHelper public function Sets the fields helper. 1
ProcessorPluginBase::setWeight public function Sets the weight for a specific processing stage. Overrides ProcessorInterface::setWeight
ProcessorPluginBase::supportsIndex public static function Checks whether this processor is applicable for a certain index. Overrides ProcessorInterface::supportsIndex 8
ProcessorPluginBase::supportsStage public function Checks whether this processor implements a particular stage. Overrides ProcessorInterface::supportsStage 2
RenderedItem::$accountSwitcher protected property The current_user service used by this plugin.
RenderedItem::$configFactory protected property Theme settings config.
RenderedItem::$renderer protected property The renderer to use.
RenderedItem::$themeInitialization protected property Theme initialization service.
RenderedItem::$themeManager protected property Theme manager service.
RenderedItem::addFieldValues public function Adds the values of properties defined by this processor to the item. Overrides ProcessorPluginBase::addFieldValues
RenderedItem::calculateDependencies public function Calculates dependencies for the configured plugin. Overrides ConfigurablePluginBase::calculateDependencies
RenderedItem::create public static function Creates an instance of the plugin. Overrides ProcessorPluginBase::create
RenderedItem::getAccountSwitcher public function Retrieves the account switcher service.
RenderedItem::getConfigFactory protected function Retrieves the config factory service.
RenderedItem::getPropertyDefinitions public function Retrieves the properties this processor defines for the given datasource. Overrides ProcessorPluginBase::getPropertyDefinitions
RenderedItem::getRenderer public function Retrieves the renderer.
RenderedItem::getThemeInitializer protected function Retrieves the theme initialization service.
RenderedItem::getThemeManager protected function Retrieves the theme manager.
RenderedItem::onDependencyRemoval public function Informs the plugin that some of its dependencies are being removed. Overrides ConfigurablePluginBase::onDependencyRemoval
RenderedItem::setAccountSwitcher public function Sets the account switcher service.
RenderedItem::setConfigFactory protected function Sets the config factory service.
RenderedItem::setRenderer public function Sets the renderer.
RenderedItem::setThemeInitializer protected function Sets the theme initialization service.
RenderedItem::setThemeManager protected function Sets the theme manager.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.