'; private const OPERATOR_GREATER_OR_EQUAL = '>='; private const OPERATOR_LESS = '<'; private const OPERATOR_LESS_OR_EQUAL = '<='; private const OPERATOR_LIKE = '*'; private const OPERATOR_NOT_LIKE = '!*'; private const OPERATOR_IN_SUB_QUERY = '=s'; private const OPERATOR_NOT_IN_SUB_QUERY = '!=s'; private string $rawKey; /** * @var mixed */ private $rawValue; /** * @param mixed $rawValue */ private function __construct(string $rawKey, $rawValue) { $this->rawKey = $rawKey; $this->rawValue = $rawValue; } public function getRaw(): array { return [$this->rawKey => $this->rawValue]; } public function getRawKey(): string { return $this->rawKey; } /** * @return mixed */ public function getRawValue() { return $this->rawValue; } /** * Create '=' comparison. * * @param Expression $arg1 An expression. * @param Expression|string|int|float|bool|null $arg2 A value (if scalar) or expression. * @return self */ public static function equal(Expression $arg1, $arg2): self { return self::createComparison(self::OPERATOR_EQUAL, $arg1, $arg2); } /** * Create '!=' comparison. * * @param Expression $arg1 An expression. * @param Expression|string|int|float|bool|null $arg2 A value (if scalar) or expression. * @return self */ public static function notEqual(Expression $arg1, $arg2): self { return self::createComparison(self::OPERATOR_NOT_EQUAL, $arg1, $arg2); } /** * Create 'LIKE' comparison. * * @param Expression $subject What to test. * @param Expression|string $pattern A pattern. * @return self */ public static function like(Expression $subject, $pattern): self { return self::createComparison(self::OPERATOR_LIKE, $subject, $pattern); } /** * Create 'NOT LIKE' comparison. * * @param Expression $subject What to test. * @param Expression|string $pattern A pattern. * @return self */ public static function notLike(Expression $subject, $pattern): self { return self::createComparison(self::OPERATOR_NOT_LIKE, $subject, $pattern); } /** * Create '>' comparison. * * @param Expression $arg1 An expression. * @param Expression|string|int|float $arg2 A value (if scalar) or expression. * @return self */ public static function greater(Expression $arg1, $arg2): self { return self::createComparison(self::OPERATOR_GREATER, $arg1, $arg2); } /** * Create '>=' comparison. * * @param Expression $arg1 An expression. * @param Expression|string|int|float $arg2 A value (if scalar) or expression. * @return self */ public static function greaterOrEqual(Expression $arg1, $arg2): self { return self::createComparison(self::OPERATOR_GREATER_OR_EQUAL, $arg1, $arg2); } /** * Create '<' comparison. * * @param Expression $arg1 An expression. * @param Expression|string|int|float $arg2 A value (if scalar) or expression. * @return self */ public static function less(Expression $arg1, $arg2): self { return self::createComparison(self::OPERATOR_LESS, $arg1, $arg2); } /** * Create '<=' comparison. * * @param Expression $arg1 An expression. * @param Expression|string|int|float $arg2 A value (if scalar) or expression. * @return self */ public static function lessOrEqual(Expression $arg1, $arg2): self { return self::createComparison(self::OPERATOR_LESS_OR_EQUAL, $arg1, $arg2); } /** * Create 'IN' comparison. * * @param Expression $subject What to test. * @param Select|scalar[] $set A set of values. A select query or array of scalars. * @return self */ public static function in(Expression $subject, $set): self { if ($set instanceof Select) { return self::createInOrNotInSubQuery(self::OPERATOR_IN_SUB_QUERY, $subject, $set); } return self::createInOrNotInArray(self::OPERATOR_EQUAL, $subject, $set); } /** * Create 'NOT IN' comparison. * * @param Expression $subject What to test. * @param Select|scalar[] $set A set of values. A select query or array of scalars. * @return self */ public static function notIn(Expression $subject, $set): self { if ($set instanceof Select) { return self::createInOrNotInSubQuery(self::OPERATOR_NOT_IN_SUB_QUERY, $subject, $set); } return self::createInOrNotInArray(self::OPERATOR_NOT_EQUAL, $subject, $set); } /** * @param Expression|string $arg1 * @param Expression|string|int|float|bool|null $arg2 */ private static function createComparison(string $operator, $arg1, $arg2): self { /** @phpstan-var mixed $arg1 */ /** @phpstan-var mixed $arg2 */ if (is_string($arg1)) { $key = $arg1; if ($key === '') { throw new RuntimeException("Expression can't be empty."); } } else if ($arg1 instanceof Expression) { $key = $arg1->getValue(); } else { throw new InvalidArgumentException("First argument must be Expression or string."); } if (substr($key, -1) === ':') { throw new RuntimeException("Expression should not end with `:`."); } $key .= $operator; if ($arg2 instanceof Expression) { $key .= ':'; $value = $arg2->getValue(); } else if (!is_scalar($arg2) && !is_null($arg2)) { throw new InvalidArgumentException("Second argument must be scalar or Expression."); } else { $value = $arg2; } return new self($key, $value); } /** * @param Expression|string $arg1 * @param scalar[] $valueList */ private static function createInOrNotInArray(string $operator, $arg1, array $valueList): self { foreach ($valueList as $item) { if (!is_scalar($item)) { throw new RuntimeException("Array items must be scalar."); } } /** @phpstan-var mixed $arg1 */ if (is_string($arg1)) { $key = $arg1; if ($key === '') { throw new RuntimeException("Expression can't be empty."); } if (substr($key, -1) === ':') { throw new RuntimeException("Expression can't end with `:`."); } } else if ($arg1 instanceof Expression) { $key = $arg1->getValue(); } else { throw new InvalidArgumentException("First argument must be Expression or string."); } $key .= $operator; return new self($key, $valueList); } /** * @param Expression|string $arg1 */ private static function createInOrNotInSubQuery(string $operator, $arg1, Select $query): self { /** @phpstan-var mixed $arg1 */ if (is_string($arg1)) { $key = $arg1; if ($key === '') { throw new RuntimeException("Expression can't be empty."); } if (substr($key, -1) === ':') { throw new RuntimeException("Expression can't end with `:`."); } } else if ($arg1 instanceof Expression) { $key = $arg1->getValue(); } else { throw new InvalidArgumentException("First argument must be Expression or string."); } $key .= $operator; return new self($key, $query->getRaw()); } }