EntityCondition.php
Same filename in other branches
Namespace
Drupal\jsonapi\QueryFile
-
core/
modules/ jsonapi/ src/ Query/ EntityCondition.php
View source
<?php
namespace Drupal\jsonapi\Query;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Http\Exception\CacheableBadRequestHttpException;
/**
* A condition object for the EntityQuery.
*
* @internal JSON:API maintains no PHP API since its API is the HTTP API. This
* class may change at any time and this will break any dependencies on it.
*
* @see https://www.drupal.org/project/drupal/issues/3032787
* @see jsonapi.api.php
*/
class EntityCondition {
/**
* The field key in the filter condition: filter[lorem][condition][<field>].
*
* @var string
*/
const PATH_KEY = 'path';
/**
* The value key in the filter condition: filter[lorem][condition][<value>].
*
* @var string
*/
const VALUE_KEY = 'value';
/**
* The operator key in the condition: filter[lorem][condition][<operator>].
*
* @var string
*/
const OPERATOR_KEY = 'operator';
/**
* The allowed condition operators.
*
* @var string[]
*/
public static $allowedOperators = [
'=',
'<>',
'>',
'>=',
'<',
'<=',
'STARTS_WITH',
'CONTAINS',
'ENDS_WITH',
'IN',
'NOT IN',
'BETWEEN',
'NOT BETWEEN',
'IS NULL',
'IS NOT NULL',
];
/**
* The field to be evaluated.
*
* @var string
*/
protected $field;
/**
* The condition operator.
*
* @var string
*/
protected $operator;
/**
* The value against which the field should be evaluated.
*
* @var mixed
*/
protected $value;
/**
* Constructs a new EntityCondition object.
*/
public function __construct($field, $value, $operator = NULL) {
$this->field = $field;
$this->value = $value;
$this->operator = $operator ? $operator : '=';
}
/**
* The field to be evaluated.
*
* @return string
* The field upon which to evaluate the condition.
*/
public function field() {
return $this->field;
}
/**
* The comparison operator to use for the evaluation.
*
* For a list of allowed operators:
*
* @see \Drupal\jsonapi\Query\EntityCondition::allowedOperators
*
* @return string
* The condition operator.
*/
public function operator() {
return $this->operator;
}
/**
* The value against which the condition should be evaluated.
*
* @return mixed
* The condition comparison value.
*/
public function value() {
return $this->value;
}
/**
* Creates an EntityCondition object from a query parameter.
*
* @param mixed $parameter
* The `filter[condition]` query parameter from the request.
*
* @return self
* An EntityCondition object with defaults.
*/
public static function createFromQueryParameter($parameter) {
static::validate($parameter);
$field = $parameter[static::PATH_KEY];
$value = isset($parameter[static::VALUE_KEY]) ? $parameter[static::VALUE_KEY] : NULL;
$operator = isset($parameter[static::OPERATOR_KEY]) ? $parameter[static::OPERATOR_KEY] : NULL;
return new static($field, $value, $operator);
}
/**
* Validates the filter has the required fields.
*/
protected static function validate($parameter) {
$valid_key_combinations = [
[
static::PATH_KEY,
static::VALUE_KEY,
],
[
static::PATH_KEY,
static::OPERATOR_KEY,
],
[
static::PATH_KEY,
static::VALUE_KEY,
static::OPERATOR_KEY,
],
];
$given_keys = array_keys($parameter);
$valid_key_set = array_reduce($valid_key_combinations, function ($valid, $set) use ($given_keys) {
return $valid ? $valid : count(array_diff($set, $given_keys)) === 0;
}, FALSE);
$has_operator_key = isset($parameter[static::OPERATOR_KEY]);
$has_path_key = isset($parameter[static::PATH_KEY]);
$has_value_key = isset($parameter[static::VALUE_KEY]);
$cacheability = (new CacheableMetadata())->addCacheContexts([
'url.query_args:filter',
]);
if (!$valid_key_set) {
// Try to provide a more specific exception is a key is missing.
if (!$has_operator_key) {
if (!$has_path_key) {
throw new CacheableBadRequestHttpException($cacheability, "Filter parameter is missing a '" . static::PATH_KEY . "' key.");
}
if (!$has_value_key) {
throw new CacheableBadRequestHttpException($cacheability, "Filter parameter is missing a '" . static::VALUE_KEY . "' key.");
}
}
// Catchall exception.
$reason = "You must provide a valid filter condition. Check that you have set the required keys for your filter.";
throw new CacheableBadRequestHttpException($cacheability, $reason);
}
if ($has_operator_key) {
$operator = $parameter[static::OPERATOR_KEY];
if (!in_array($operator, static::$allowedOperators)) {
$reason = "The '" . $operator . "' operator is not allowed in a filter parameter.";
throw new CacheableBadRequestHttpException($cacheability, $reason);
}
if (in_array($operator, [
'IS NULL',
'IS NOT NULL',
]) && $has_value_key) {
$reason = "Filters using the '" . $operator . "' operator should not provide a value.";
throw new CacheableBadRequestHttpException($cacheability, $reason);
}
}
}
}
Classes
Title | Deprecated | Summary |
---|---|---|
EntityCondition | A condition object for the EntityQuery. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.