entity_hierarchy-8.x-2.24/src/Storage/QueryBuilder.php

src/Storage/QueryBuilder.php
<?php

declare(strict_types=1);

namespace Drupal\entity_hierarchy\Storage;

use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Psr\Log\LoggerInterface;

/**
 * The query builder for a specific hierarchical field instance.
 */
class QueryBuilder {

  use QueryBuilderTrait;

  /**
   * Constructor for query builder.
   *
   * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $fieldStorageDefinition
   *   The field storage for this hierarchy field.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manage service.
   * @param \Drupal\Core\Database\Connection $database
   *   The database connection service.
   * @param \Psr\Log\LoggerInterface $logger
   *   The logger service.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function __construct(
    protected readonly FieldStorageDefinitionInterface $fieldStorageDefinition,
    protected readonly EntityTypeManagerInterface $entityTypeManager,
    protected readonly Connection $database,
    protected readonly LoggerInterface $logger,
  ) {
    $this->setupTablesAndColumns();
  }

  /**
   * Find the ancestor records of an entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity to find the ancestors of.
   *
   * @return \Drupal\entity_hierarchy\Storage\RecordCollection
   *   The collection of records returned for the ancestor query.
   */
  public function findAncestors(ContentEntityInterface $entity): RecordCollection {
    $sql = $this->getAncestorSql() . " SELECT * FROM ancestors ORDER BY depth";
    $result = $this->database->query($sql, [
      ':id' => $entity->id(),
      ':revisionId' => $entity->getRevisionId() ?: $entity->id(),
    ]);
    $type = $this->fieldStorageDefinition->getTargetEntityTypeId();
    $records = $result->fetchAll(\PDO::FETCH_CLASS, Record::class, [$type]);
    if (!$this->fieldStorageDefinition->isBaseField()) {
      // Drupal doesn't store an empty row for a NULL parent. Add it back in.
      if ($first_record = reset($records)) {
        $record = Record::create($type, $first_record->getTargetId(), 0, $first_record->getDepth() - 1);
      }
      else {
        $record = Record::create($type, (int) $entity->id(), 0, 0);
      }
      array_unshift($records, $record);
    }
    return new RecordCollection($records);
  }

  /**
   * Find the root record of an entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity to find the depth of.
   *
   * @return \Drupal\entity_hierarchy\Storage\Record
   *   The root record of an ancestor query.
   */
  public function findRoot(ContentEntityInterface $entity): ?Record {
    $ancestors = $this->findAncestors($entity);
    // Convert FALSE to NULL.
    return $ancestors->getIterator()->current() ?: NULL;
  }

  /**
   * Find the parent of an entity.
   *
   * This isn't really a query builder function but adding here for
   * completeness.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity to find the depth of.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   *   The parent entity of an entity.
   */
  public function findParent(ContentEntityInterface $entity): ?ContentEntityInterface {
    $field_name = $this->fieldStorageDefinition->getName();
    if (!$entity->hasField($field_name)) {
      return NULL;
    }
    return $entity->get($field_name)->entity;
  }

  /**
   * Find the depth of an entity from the root.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity to find the depth of.
   *
   * @return int
   *   The depth.
   */
  public function findDepth(ContentEntityInterface $entity): int {
    $sql = $this->getAncestorSql() . " SELECT depth FROM ancestors ORDER BY depth LIMIT 1";
    $result = $this->database->query($sql, [
      ':id' => $entity->id(),
      ':revisionId' => $entity->getRevisionId() ?: $entity->id(),
    ]);
    if ($object = $result->fetchObject()) {
      $depth = $object->depth * -1;
      if (!$this->fieldStorageDefinition->isBaseField()) {
        // Non base fields don't have a record where parent is null. Compensate.
        $depth = $depth + 1;
      }
      return $depth;
    }
    return 0;
  }

  /**
   * Find the descendant records of an entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity to find the descendants of.
   * @param int $depth
   *   The depth of descendants to load.
   * @param int $start
   *   The starting depth.
   *
   * @return \Drupal\entity_hierarchy\Storage\RecordCollection
   *   A collection of records reflecting the descendants of the entity.
   */
  public function findDescendants(ContentEntityInterface $entity, int $depth = 0, int $start = 1): RecordCollection {
    $sql = $this->getDescendantSql() . " SELECT id, revisionId, targetId, weight, depth FROM descendants WHERE depth >= :start";
    $params = [
      ':targetId' => $entity->id(),
      ':start' => $start,
    ];
    if ($depth > 0) {
      $sql .= " AND depth < :depth";
      $params[':depth'] = $start + $depth;
    }
    $sql .= " ORDER by weight, id";
    $result = $this->database->query($sql, $params);
    $type = $this->fieldStorageDefinition->getTargetEntityTypeId();
    $records = $result->fetchAll(\PDO::FETCH_CLASS, Record::class, [$type]);
    return new RecordCollection($records);
  }

  /**
   * Helper function to only find depth 1 descendants.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity to check.
   *
   * @return \Drupal\entity_hierarchy\Storage\RecordCollection
   *   A collection of records reflecting the children of the entity.
   */
  public function findChildren(ContentEntityInterface $entity): RecordCollection {
    return $this->findDescendants($entity, 1);
  }

}

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

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