X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;ds=sidebyside;f=web%2Fmodules%2Fcontrib%2Fentity%2Fsrc%2FQueryAccess%2FEntityQueryAlter.php;fp=web%2Fmodules%2Fcontrib%2Fentity%2Fsrc%2FQueryAccess%2FEntityQueryAlter.php;h=25c7395c826f117e1e1c3429447fd5ff2c39c1e2;hb=f3baf763d342a5f82576890e2a8111a5aaf139dc;hp=0000000000000000000000000000000000000000;hpb=059867c3f96750652c80f39e44c442a58c2549ee;p=yaffs-website diff --git a/web/modules/contrib/entity/src/QueryAccess/EntityQueryAlter.php b/web/modules/contrib/entity/src/QueryAccess/EntityQueryAlter.php new file mode 100644 index 000000000..25c7395c8 --- /dev/null +++ b/web/modules/contrib/entity/src/QueryAccess/EntityQueryAlter.php @@ -0,0 +1,181 @@ +entityFieldManager = $entity_field_manager; + $this->entityTypeManager = $entity_type_manager; + $this->renderer = $renderer; + $this->requestStack = $request_stack; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity_field.manager'), + $container->get('entity_type.manager'), + $container->get('renderer'), + $container->get('request_stack') + ); + } + + /** + * Alters the select query for the given entity type. + * + * @param \Drupal\Core\Database\Query\SelectInterface $query + * The select query. + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type. + */ + public function alter(SelectInterface $query, EntityTypeInterface $entity_type) { + if (!$entity_type->hasHandlerClass('query_access')) { + return; + } + $entity_type_id = $entity_type->id(); + $storage = $this->entityTypeManager->getStorage($entity_type_id); + if (!$storage instanceof SqlContentEntityStorage) { + return; + } + + /** @var \Drupal\entity\QueryAccess\QueryAccessHandlerInterface $query_access */ + $query_access = $this->entityTypeManager->getHandler($entity_type_id, 'query_access'); + $conditions = $query_access->getConditions('view'); + if ($conditions->isAlwaysFalse()) { + $query->where('1 = 0'); + } + elseif (count($conditions)) { + $sql_conditions = $this->mapConditions($conditions, $query); + $query->condition($sql_conditions); + } + + $this->applyCacheability(CacheableMetadata::createFromObject($conditions)); + } + + /** + * Maps an entity type's access conditions to SQL conditions. + * + * @param \Drupal\entity\QueryAccess\ConditionGroup $conditions + * The access conditions. + * @param \Drupal\Core\Database\Query\SelectInterface $query + * The SQL query. + * @param bool $nested_inside_or + * Whether the access conditions are nested inside an OR condition. + * + * @return \Drupal\Core\Database\Query\ConditionInterface + * The SQL conditions. + */ + protected function mapConditions(ConditionGroup $conditions, SelectInterface $query, $nested_inside_or = FALSE) { + $sql_condition = $query->conditionGroupFactory($conditions->getConjunction()); + $tables = new Tables($query); + $nested_inside_or = $nested_inside_or || $conditions->getConjunction() == 'OR'; + foreach ($conditions->getConditions() as $condition) { + if ($condition instanceof ConditionGroup) { + $nested_sql_conditions = $this->mapConditions($condition, $query, $nested_inside_or); + $sql_condition->condition($nested_sql_conditions); + } + else { + // Access conditions don't specify a langcode. + $langcode = NULL; + $type = $nested_inside_or || $condition->getOperator() === 'IS NULL' ? 'LEFT' : 'INNER'; + $sql_field = $tables->addField($condition->getField(), $type, $langcode); + $value = $condition->getValue(); + $operator = $condition->getOperator(); + // Using LIKE/NOT LIKE ensures a case insensitive comparison. + // @see \Drupal\Core\Entity\Query\Sql\Condition::translateCondition(). + $case_sensitive = $tables->isFieldCaseSensitive($condition->getField()); + $operator_map = [ + '=' => 'LIKE', + '<>' => 'NOT LIKE', + ]; + if (!$case_sensitive && isset($operator_map[$operator])) { + $operator = $operator_map[$operator]; + $value = $query->escapeLike($value); + } + + $sql_condition->condition($sql_field, $value, $operator); + } + } + + return $sql_condition; + } + + /** + * Applies the cacheablity metadata to the current request. + * + * @param \Drupal\Core\Cache\CacheableMetadata $cacheable_metadata + * The cacheability metadata. + */ + protected function applyCacheability(CacheableMetadata $cacheable_metadata) { + $request = $this->requestStack->getCurrentRequest(); + if ($request->isMethodCacheable() && $this->renderer->hasRenderContext()) { + $build = []; + $cacheable_metadata->applyTo($build); + $this->renderer->render($build); + } + } + +}