acquia_perz-4.0.0-rc1/src/EntityHelper.php

src/EntityHelper.php
<?php

namespace Drupal\acquia_perz;

use Drupal\acquia_perz\Session\AcquiaPerzUserSession;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\ContentEntityType;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Session\UserSession;
use Drupal\field\Entity\FieldConfig;

/**
 * Entity helper service.
 */
class EntityHelper {

  const ENTITY_CONFIG_NAME = 'acquia_perz.entity_config';

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The entity field manager.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * The renderer service.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * The date formatter service.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected $dateFormatter;

  /**
   * The time service.
   *
   * @var \Drupal\Component\Datetime\TimeInterface
   */
  protected $time;

  /**
   * The config factory service.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The database service.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * The File Url Generator.
   *
   * @var \Drupal\Core\File\FileUrlGeneratorInterface
   */
  protected $fileUrlGenerator;

  /**
   * The rendered user.
   *
   * @var \Drupal\Core\Session\UserSession
   */
  protected $renderUser;

  /**
   * Constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   Entity type manager service.
   * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
   *   Entity field manager service.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer service.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory service.
   * @param \Drupal\Core\Database\Connection $database
   *   The database connection to be used.
   * @param \Drupal\Core\File\FileUrlGeneratorInterface $file_url_generator
   *   The File url generator service.
   */
  public function __construct(
    EntityTypeManagerInterface $entity_type_manager,
    EntityFieldManagerInterface $entity_field_manager,
    RendererInterface $renderer,
    DateFormatterInterface $date_formatter,
    TimeInterface $time,
    ConfigFactoryInterface $config_factory,
    Connection $database,
    FileUrlGeneratorInterface $file_url_generator,
  ) {
    $this->entityTypeManager = $entity_type_manager;
    $this->entityFieldManager = $entity_field_manager;
    $this->renderer = $renderer;
    $this->dateFormatter = $date_formatter;
    $this->time = $time;
    $this->configFactory = $config_factory;
    $this->database = $database;
    $this->fileUrlGenerator = $file_url_generator;
  }

  /**
   * Is Eligible for export.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The current entity.
   */
  public function isEligibleForExport(EntityInterface $entity): bool {
    $view_modes = $this->getEntityViewModesSettingValue($entity);
    if (empty($view_modes)) {
      return FALSE;
    }
    foreach ($view_modes as $view_mode) {
      if (isset($view_mode['only_export_specific_entities'])) {
        return (bool) PerzHelper::getExportFieldValue($entity, $view_mode['only_export_specific_entities']);
      }
    }
    return TRUE;
  }

  /**
   * Is valid entity.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The current entity.
   */
  public function isValidEntity(EntityInterface $entity): bool {
    $view_modes = $this->getEntityViewModesSettingValue($entity);
    if (empty($view_modes)) {
      return FALSE;
    }
    return TRUE;
  }

  /**
   * Returns the value of the entity view modes setting.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The current entity.
   *
   * @return array
   *   The setting value.
   */
  public function getEntityViewModesSettingValue(EntityInterface $entity): array {
    $view_modes = $this->configFactory
      ->get('acquia_perz.entity_config')->get("view_modes.{$entity->getEntityTypeId()}.{$entity->bundle()}");
    if ($view_modes) {
      return $view_modes;
    }
    return [];
  }

  /**
   * Get entity query.
   *
   * @param string $entity_type_id
   *   The entity type id.
   * @param array $bundles
   *   List of bundles of entity type.
   * @param int $offset
   *   The query offset.
   * @param int $limit
   *   The query limit.
   *
   * @return \Drupal\Core\Entity\Query\QueryInterface
   *   Returns entity query.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function getEntitiesQuery(string $entity_type_id, array $bundles, int $offset = NULL, int $limit = NULL): QueryInterface {
    // Check only bundles with at least one view mode activated
    // besides 'acquia_perz_preview_image' view mode.
    $available_bundles = [];
    foreach ($bundles as $bundle => $view_modes) {
      $view_modes = array_keys($view_modes);
      if (count($view_modes) === 1
        && in_array('acquia_perz_preview_image', $view_modes)) {
        continue;
      }
      $available_bundles[] = $bundle;
    }
    // Skip entity type without activated bundles.
    if (empty($available_bundles)) {
      return [];
    }
    $bundle_property_name = $this
      ->entityTypeManager
      ->getStorage($entity_type_id)
      ->getEntityType()
      ->getKey('bundle');
    $query = $this
      ->entityTypeManager
      ->getStorage($entity_type_id)
      ->getQuery();
    // For single-bundle entity types like 'user'
    // we don't use bundle related property.
    if (!empty($bundle_property_name)) {
      $query = $query->condition($bundle_property_name, $available_bundles, 'IN');
    }
    if ($entity_type_id === 'user') {
      $query = $query->condition('uid', 0, '<>');
    }
    if ($offset !== NULL && $limit !== NULL) {
      $query->range($offset, $limit);
    }

    return $query;
  }

  /**
   * Get entities query count by entity type and available bundles.
   *
   * @param string $entity_type_id
   *   The entity type id.
   * @param array $bundles
   *   List of bundles and its view modes of entity type.
   *   Format:
   *   [
   *    'page' => [
   *       'default' => 1,
   *       'view_mode2' => 1,
   *       ...
   *    ]
   *   ].
   * @param int|null $offset
   *   The query offset.
   * @param int|null $limit
   *   The query limit.
   *
   * @return int
   *   Returns number of entities.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function getCountByEntityTypeId(string $entity_type_id, array $bundles, int $offset = NULL, int $limit = NULL): int {
    $query = $this->getEntitiesQuery($entity_type_id, $bundles, $offset, $limit);
    return (int) $query->accessCheck(TRUE)->count()->execute();
  }

  /**
   * Get single entity uuid by entity id and its entity type.
   *
   * @param \Drupal\Core\Entity\ContentEntityType $entity_type
   *   Entity type object.
   * @param int $entity_id
   *   The entity id.
   *
   * @return string
   *   Returns entity uuid.
   */
  public function getEntityUuidById(ContentEntityType $entity_type, int $entity_id): string {
    $query = $this->database->select($entity_type->get('base_table'), 't');
    $query->addField('t', 'uuid');
    $query->condition($entity_type->getKey('id'), $entity_id);
    $query->range(0, 1);
    return $query->execute()->fetchField();
  }

  /**
   * Get rendered content.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The current entity.
   * @param string $view_mode
   *   The view mode.
   * @param string $langcode
   *   The language code.
   */
  public function getRenderedContent(EntityInterface $entity, string $view_mode, string $langcode) {
    $elements = [];
    $render_role = $this->getEntityRenderRole($entity, $view_mode);
    $account = $this->getRenderUser($render_role);
    PerzHelper::switchAccountTo($account);
    $entity_access = $entity->access('view', $account, FALSE);
    if ($entity_access) {
      $elements = PerzHelper::getViewModeMinimalHtml($entity, $view_mode, $langcode);
    }
    // We don't use the DeprecationHelper class because then the $elements
    // variable isn't passed by reference, losing the attached libraries.
    $currentVersion = \Drupal::VERSION;
    $normalizedVersion = str_ends_with($currentVersion, '-dev') ? str_replace(['.x-dev', '-dev'], '.0', $currentVersion) : $currentVersion;
    if (version_compare($normalizedVersion, '10.3', '>=')) {
      $render_content = $this->renderer->renderInIsolation($elements);
    }
    else {
      $render_content = $this->renderer->renderPlain($elements);
    }

    // Add additional styles added by Site Studio for components.
    // Site Studio adds internal CSS styles specific to components
    // while rendering.
    // Since Personalization injects rendered HTML on the client site,
    // it is necessary to have the additional styles for components included
    // in rendered HTML in order to make components work as expected.
    if ($this->configFactory->get('acquia_perz.settings')->get('advanced.dynamic_js_support')
      && !empty($elements['#attached']['library'])) {
      PerzHelper::saveLibrariesForPerz($entity->uuid(), $elements['#attached']['library']);
    }

    if (!empty($elements['#attached']['cohesion'])) {
      $attachment = implode('', $elements['#attached']['cohesion']);
      $render_content .= $attachment;
    }
    PerzHelper::switchAccountBack();
    return $render_content;
  }

  /**
   * Export entity by view mode.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The current entity.
   * @param string $view_mode
   *   The view mode.
   * @param string $langcode
   *   The language code.
   *
   * @return array
   *   Array of entities.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function getEntityVariation(EntityInterface $entity, string $view_mode, string $langcode): array {
    $render_role = $this->getEntityRenderRole($entity, $view_mode);
    $rendered_data = $this->getRenderedContent($entity, $view_mode, $langcode);
    $entity_label = !empty($rendered_data) ? $entity->label() : $entity->label() . ' (no content)';
    $personalization_label = $this->getPersonalizationLabel($entity, $view_mode);
    if ($personalization_label !== '') {
      $entity_label = $personalization_label;
    }

    if ($entity->getEntityTypeId() == 'paragraph' || $entity->getEntityTypeId() == 'component_content') {
      $url = NULL;
    }
    else {
      $urlObject = $entity->toUrl()->toString(TRUE);
      $url = $urlObject->getGeneratedUrl();
    }

    $preview_image = NULL;
    $config = $this->configFactory->get(EntityHelper::ENTITY_CONFIG_NAME);
    $config_image_preview_name = 'view_modes.' . $entity->getEntityTypeId() . '.' . $entity->bundle() . '.' . $view_mode . '.preview_image';
    $config_view_modes = $config->get($config_image_preview_name);
    if (!empty($config_view_modes)) {
      $preview_image_field = $entity->getConfigTarget();
      if (!empty($preview_image_field)) {
        $preview_image = $this->fileUrlGenerator->generateAbsoluteString($preview_image_field);
      }
    }

    $result = [
      'content_uuid' => $entity->uuid(),
      'content_type' => $entity->bundle(),
      'view_mode' => $view_mode,
      'language' => $langcode,
      'number_view' => 0,
      'label' => $entity_label,
      'updated' => $this->dateFormatter->format($this->time->getCurrentTime(), 'custom', 'Y-m-d\TH:i:s'),
      'rendered_data' => !empty($rendered_data) ? $rendered_data : '<!-- PERZ DEBUG: this content cannot be accessed by the render role ' . $render_role . '  -->',
      'base_url' => PerzHelper::getSiteDomainWithHost(),
      'url' => $url,
      'preview_image' => $preview_image,
    ];
    $taxonomy_relations = $this->getEntityTaxonomyRelations($entity);
    if ($taxonomy_relations) {
      $result['relations'] = $taxonomy_relations;
    }
    return $result;
  }

  /**
   * Get array of related taxonomy term fields/term uuids.
   *
   * Only taxonomies that are checked on Entity settings form.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The target entity.
   *
   * @return array
   *   Returns array of related taxonomy term fields/term uuids.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function getEntityTaxonomyRelations(EntityInterface $entity): array {
    $relations = [];
    $entity_type_id = $entity->getEntityTypeId();
    $bundle = $entity->bundle();
    $view_modes = $this->getEntityTypesConfig();
    $available_taxonomies = [];
    if (isset($view_modes['taxonomy_term'])) {
      $available_taxonomies = array_keys($view_modes['taxonomy_term']);
    }
    $fields = $this->entityFieldManager
      ->getFieldDefinitions($entity_type_id, $bundle);
    foreach ($fields as $field) {
      if ($field instanceof FieldConfig
        && $field->getType() === 'entity_reference'
        && $field->getSetting('handler') === 'default:taxonomy_term'
      ) {
        $field_name = $field->getName();
        $settings = $field->getSetting('handler_settings');
        $field_taxonomies = $settings['target_bundles'];
        // Check if field contains at least one available taxonomy.
        if (count(array_intersect($available_taxonomies, $field_taxonomies)) == 0) {
          continue;
        }
        $terms = $entity->$field_name->getValue();
        $available_field_terms = [];
        foreach ($terms as $term) {
          $term_entity = $this->entityTypeManager
            ->getStorage('taxonomy_term')
            ->load($term['target_id']);
          $term_uuid = $term_entity->uuid();
          if (in_array($term_entity->bundle(), $available_taxonomies)) {
            $available_field_terms[] = $term_uuid;
          }
        }
        // Skip fields without any terms.
        if (!empty($available_field_terms)) {
          $relations[] = [
            'field' => $field_name,
            'terms' => $available_field_terms,
          ];
        }
      }
    }
    return $relations;
  }

  /**
   * Get list of available types > bundles > view modes.
   *
   * @return array|mixed|null
   *   Returns a list of available types > bundles > view modes.
   */
  public function getEntityTypesConfig(): mixed {
    return $this->configFactory
      ->get('acquia_perz.entity_config')
      ->get('view_modes');
  }

  /**
   * Get rendered user.
   *
   * @param string $render_role
   *   The render user role.
   *
   * @return \Drupal\acquia_perz\Session\AcquiaPerzUserSession|\Drupal\Core\Session\UserSession
   *   The rendered user.
   */
  public function getRenderUser(string $render_role): AcquiaPerzUserSession|UserSession {
    if (!$this->renderUser) {
      $this->renderUser = new AcquiaPerzUserSession($render_role);
    }
    return $this->renderUser;
  }

  /**
   * Returns the value of render role from the entity.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The current entity.
   * @param string $view_mode
   *   The view mode value.
   *
   * @return string
   *   The render role value.
   */
  public function getEntityRenderRole(EntityInterface $entity, string $view_mode): string {
    $render_role = 'anonymous';
    $view_modes = $this->getEntityViewModesSettingValue($entity);
    if ($view_modes) {
      $render_role = $view_modes[$view_mode]['render_role'];
    }
    return $render_role;
  }

  /**
   * Returns the Personalization Label of entity.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The current entity.
   * @param string $view_mode
   *   The view mode value.
   *
   * @return string
   *   The Label to set in Personalization.
   */
  public function getPersonalizationLabel(EntityInterface $entity, string $view_mode): string {
    $personalization_label = '';
    $view_modes = $this->getEntityViewModesSettingValue($entity);
    if ($view_modes) {
      $personalization_label_field = $view_modes[$view_mode]['personalization_label'] ?? '';
      if ($personalization_label_field !== '' && $personalization_label_field !== 'default') {
        if ($entity->$personalization_label_field) {
          $personalization_label = $entity->$personalization_label_field->value;
        }
      }
    }
    return $personalization_label;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc