123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- <?php
- namespace Drupal\Core\Entity\Query;
- use Drupal\Core\Database\Query\PagerSelectExtender;
- use Drupal\Core\Entity\EntityTypeInterface;
- /**
- * The base entity query class.
- */
- abstract class QueryBase implements QueryInterface {
- /**
- * The entity type this query runs against.
- *
- * @var string
- */
- protected $entityTypeId;
- /**
- * Information about the entity type.
- *
- * @var \Drupal\Core\Entity\EntityTypeInterface
- */
- protected $entityType;
- /**
- * The list of sorts.
- *
- * @var array
- */
- protected $sort = [];
- /**
- * TRUE if this is a count query, FALSE if it isn't.
- *
- * @var bool
- */
- protected $count = FALSE;
- /**
- * Conditions.
- *
- * @var \Drupal\Core\Entity\Query\ConditionInterface
- */
- protected $condition;
- /**
- * The list of aggregate expressions.
- *
- * @var array
- */
- protected $aggregate = [];
- /**
- * The list of columns to group on.
- *
- * @var array
- */
- protected $groupBy = [];
- /**
- * Aggregate Conditions
- *
- * @var \Drupal\Core\Entity\Query\ConditionAggregateInterface
- */
- protected $conditionAggregate;
- /**
- * The list of sorts over the aggregate results.
- *
- * @var array
- */
- protected $sortAggregate = [];
- /**
- * The query range.
- *
- * @var array
- */
- protected $range = [];
- /**
- * The query metadata for alter purposes.
- *
- * @var array
- */
- protected $alterMetaData;
- /**
- * The query tags.
- *
- * @var array
- */
- protected $alterTags;
- /**
- * Whether access check is requested or not. Defaults to TRUE.
- *
- * @var bool
- */
- protected $accessCheck = TRUE;
- /**
- * Flag indicating whether to query the current revision or all revisions.
- *
- * @var bool
- */
- protected $allRevisions = FALSE;
- /**
- * Flag indicating whether to query the latest revision.
- *
- * @var bool
- */
- protected $latestRevision = FALSE;
- /**
- * The query pager data.
- *
- * @var array
- *
- * @see Query::pager()
- */
- protected $pager = [];
- /**
- * List of potential namespaces of the classes belonging to this query.
- *
- * @var array
- */
- protected $namespaces = [];
- /**
- * Constructs this object.
- *
- * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
- * The entity type definition.
- * @param string $conjunction
- * - AND: all of the conditions on the query need to match.
- * - OR: at least one of the conditions on the query need to match.
- * @param array $namespaces
- * List of potential namespaces of the classes belonging to this query.
- */
- public function __construct(EntityTypeInterface $entity_type, $conjunction, array $namespaces) {
- $this->entityTypeId = $entity_type->id();
- $this->entityType = $entity_type;
- $this->conjunction = $conjunction;
- $this->namespaces = $namespaces;
- $this->condition = $this->conditionGroupFactory($conjunction);
- if ($this instanceof QueryAggregateInterface) {
- $this->conditionAggregate = $this->conditionAggregateGroupFactory($conjunction);
- }
- }
- /**
- * {@inheritdoc}
- */
- public function getEntityTypeId() {
- return $this->entityTypeId;
- }
- /**
- * {@inheritdoc}
- */
- public function condition($property, $value = NULL, $operator = NULL, $langcode = NULL) {
- $this->condition->condition($property, $value, $operator, $langcode);
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function exists($property, $langcode = NULL) {
- $this->condition->exists($property, $langcode);
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function notExists($property, $langcode = NULL) {
- $this->condition->notExists($property, $langcode);
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function range($start = NULL, $length = NULL) {
- $this->range = [
- 'start' => $start,
- 'length' => $length,
- ];
- return $this;
- }
- /**
- * Creates an object holding a group of conditions.
- *
- * See andConditionGroup() and orConditionGroup() for more.
- *
- * @param string $conjunction
- * - AND (default): this is the equivalent of andConditionGroup().
- * - OR: this is the equivalent of orConditionGroup().
- *
- * @return \Drupal\Core\Entity\Query\ConditionInterface
- * An object holding a group of conditions.
- */
- protected function conditionGroupFactory($conjunction = 'AND') {
- $class = static::getClass($this->namespaces, 'Condition');
- return new $class($conjunction, $this, $this->namespaces);
- }
- /**
- * {@inheritdoc}
- */
- public function andConditionGroup() {
- return $this->conditionGroupFactory('and');
- }
- /**
- * {@inheritdoc}
- */
- public function orConditionGroup() {
- return $this->conditionGroupFactory('or');
- }
- /**
- * {@inheritdoc}
- */
- public function sort($field, $direction = 'ASC', $langcode = NULL) {
- $this->sort[] = [
- 'field' => $field,
- 'direction' => strtoupper($direction),
- 'langcode' => $langcode,
- ];
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function count() {
- $this->count = TRUE;
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function accessCheck($access_check = TRUE) {
- $this->accessCheck = $access_check;
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function currentRevision() {
- $this->allRevisions = FALSE;
- $this->latestRevision = FALSE;
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function latestRevision() {
- $this->allRevisions = TRUE;
- $this->latestRevision = TRUE;
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function allRevisions() {
- $this->allRevisions = TRUE;
- $this->latestRevision = FALSE;
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function pager($limit = 10, $element = NULL) {
- // Even when not using SQL, storing the element PagerSelectExtender is as
- // good as anywhere else.
- if (!isset($element)) {
- $element = PagerSelectExtender::$maxElement++;
- }
- elseif ($element >= PagerSelectExtender::$maxElement) {
- PagerSelectExtender::$maxElement = $element + 1;
- }
- $this->pager = [
- 'limit' => $limit,
- 'element' => $element,
- ];
- return $this;
- }
- /**
- * Gets the total number of results and initialize a pager for the query.
- *
- * The pager can be disabled by either setting the pager limit to 0, or by
- * setting this query to be a count query.
- */
- protected function initializePager() {
- if ($this->pager && !empty($this->pager['limit']) && !$this->count) {
- $page = pager_find_page($this->pager['element']);
- $count_query = clone $this;
- $this->pager['total'] = $count_query->count()->execute();
- $this->pager['start'] = $page * $this->pager['limit'];
- pager_default_initialize($this->pager['total'], $this->pager['limit'], $this->pager['element']);
- $this->range($this->pager['start'], $this->pager['limit']);
- }
- }
- /**
- * {@inheritdoc}
- */
- public function tableSort(&$headers) {
- // If 'field' is not initialized, the header columns aren't clickable.
- foreach ($headers as $key => $header) {
- if (is_array($header) && isset($header['specifier'])) {
- $headers[$key]['field'] = '';
- }
- }
- $order = tablesort_get_order($headers);
- $direction = tablesort_get_sort($headers);
- foreach ($headers as $header) {
- if (is_array($header) && ($header['data'] == $order['name'])) {
- $this->sort($header['specifier'], $direction, isset($header['langcode']) ? $header['langcode'] : NULL);
- }
- }
- return $this;
- }
- /**
- * Makes sure that the Condition object is cloned as well.
- */
- public function __clone() {
- $this->condition = clone $this->condition;
- }
- /**
- * {@inheritdoc}
- */
- public function addTag($tag) {
- $this->alterTags[$tag] = 1;
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function hasTag($tag) {
- return isset($this->alterTags[$tag]);
- }
- /**
- * {@inheritdoc}
- */
- public function hasAllTags() {
- return !(boolean) array_diff(func_get_args(), array_keys($this->alterTags));
- }
- /**
- * {@inheritdoc}
- */
- public function hasAnyTag() {
- return (boolean) array_intersect(func_get_args(), array_keys($this->alterTags));
- }
- /**
- * {@inheritdoc}
- */
- public function addMetaData($key, $object) {
- $this->alterMetaData[$key] = $object;
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function getMetaData($key) {
- return isset($this->alterMetaData[$key]) ? $this->alterMetaData[$key] : NULL;
- }
- /**
- * {@inheritdoc}
- */
- public function aggregate($field, $function, $langcode = NULL, &$alias = NULL) {
- if (!isset($alias)) {
- $alias = $this->getAggregationAlias($field, $function);
- }
- $this->aggregate[$alias] = [
- 'field' => $field,
- 'function' => $function,
- 'alias' => $alias,
- 'langcode' => $langcode,
- ];
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function conditionAggregate($field, $function = NULL, $value = NULL, $operator = '=', $langcode = NULL) {
- $this->aggregate($field, $function, $langcode);
- $this->conditionAggregate->condition($field, $function, $value, $operator, $langcode);
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function sortAggregate($field, $function, $direction = 'ASC', $langcode = NULL) {
- $alias = $this->getAggregationAlias($field, $function);
- $this->sortAggregate[$alias] = [
- 'field' => $field,
- 'function' => $function,
- 'direction' => $direction,
- 'langcode' => $langcode,
- ];
- $this->aggregate($field, $function, $langcode, $alias);
- return $this;
- }
- /**
- * {@inheritdoc}
- */
- public function groupBy($field, $langcode = NULL) {
- $this->groupBy[] = [
- 'field' => $field,
- 'langcode' => $langcode,
- ];
- return $this;
- }
- /**
- * Generates an alias for a field and its aggregated function.
- *
- * @param string $field
- * The field name used in the alias.
- * @param string $function
- * The aggregation function used in the alias.
- *
- * @return string
- * The alias for the field.
- */
- protected function getAggregationAlias($field, $function) {
- return strtolower($field . '_' . $function);
- }
- /**
- * Gets a list of namespaces of the ancestors of a class.
- *
- * @param $object
- * An object within a namespace.
- *
- * @return array
- * A list containing the namespace of the class, the namespace of the
- * parent of the class and so on and so on.
- */
- public static function getNamespaces($object) {
- $namespaces = [];
- for ($class = get_class($object); $class; $class = get_parent_class($class)) {
- $namespaces[] = substr($class, 0, strrpos($class, '\\'));
- }
- return $namespaces;
- }
- /**
- * Finds a class in a list of namespaces.
- *
- * @param array $namespaces
- * A list of namespaces.
- * @param string $short_class_name
- * A class name without namespace.
- *
- * @return string
- * The fully qualified name of the class.
- */
- public static function getClass(array $namespaces, $short_class_name) {
- foreach ($namespaces as $namespace) {
- $class = $namespace . '\\' . $short_class_name;
- if (class_exists($class)) {
- return $class;
- }
- }
- }
- }
|