pdo-document/src/Field.php

199 lines
7.9 KiB
PHP
Raw Normal View History

<?php
/**
* @author Daniel J. Summers <daniel@bitbadger.solutions>
* @license MIT
*/
declare(strict_types=1);
namespace BitBadger\PDODocument;
use Exception;
/**
* Criteria for a field WHERE clause
*/
class Field
{
/**
* Constructor
*
* NOTE: Use static construction methods rather than using this directly; different properties are required
* depending on the operation being performed. This is only public so it can be tested.
*
* @param string $fieldName The name of the field
* @param Op $op The operation by which the field will be compared
* @param mixed $value The value of the field
* @param string $paramName The name of the parameter to which this should be bound
* @param string $qualifier A table qualifier for the `data` column
*/
public function __construct(public string $fieldName = '', public Op $op = Op::EQ, public mixed $value = '',
public string $paramName = '', public string $qualifier = '') { }
/**
* Append the parameter name and value to the given associative array
*
* @param array $existing The existing parameters
* @return array The given parameter array with this field's name and value appended
*/
public function appendParameter(array $existing): array
{
switch ($this->op) {
case Op::EX:
case Op::NEX:
break;
case Op::BT:
$existing["{$this->paramName}min"] = $this->value[0];
$existing["{$this->paramName}max"] = $this->value[1];
break;
default:
$existing[$this->paramName] = $this->value;
}
return $existing;
}
/**
* Get the WHERE clause fragment for this parameter
*
* @return string The WHERE clause fragment for this parameter
* @throws Exception|DocumentException If the database mode has not been set
*/
public function toWhere(): string
{
$mode = Configuration::mode('make field WHERE clause');
$fieldName = (empty($this->qualifier) ? '' : "$this->qualifier.") . 'data' . match (true) {
!str_contains($this->fieldName, '.') => "->>'$this->fieldName'",
$mode === Mode::PgSQL => "#>>'{" . implode(',', explode('.', $this->fieldName)) . "}'",
$mode === Mode::SQLite => "->>'" . implode("'->>'", explode('.', $this->fieldName)) . "'"
};
$fieldPath = match ($mode) {
Mode::PgSQL => match (true) {
$this->op === Op::BT => is_numeric($this->value[0]) ? "($fieldName)::numeric" : $fieldName,
is_numeric($this->value) => "($fieldName)::numeric",
default => $fieldName
},
default => $fieldName
};
$criteria = match ($this->op) {
Op::EX, Op::NEX => '',
Op::BT => " {$this->paramName}min AND {$this->paramName}max",
default => " $this->paramName"
};
return $fieldPath . ' ' . $this->op->toSQL() . $criteria;
}
/**
* Create an equals (=) field criterion
*
* @param string $fieldName The name of the field against which the value will be compared
* @param mixed $value The value for which equality will be checked
* @param string $paramName The name of the parameter to which this should be bound (optional; generated if blank)
* @return static The field with the requested criterion
*/
public static function EQ(string $fieldName, mixed $value, string $paramName = ''): static
{
return new static($fieldName, Op::EQ, $value, $paramName);
}
/**
* Create a greater than (>) field criterion
*
* @param string $fieldName The name of the field against which the value will be compared
* @param mixed $value The value for the greater than comparison
* @param string $paramName The name of the parameter to which this should be bound (optional; generated if blank)
* @return static The field with the requested criterion
*/
public static function GT(string $fieldName, mixed $value, string $paramName = ''): static
{
return new static($fieldName, Op::GT, $value, $paramName);
}
/**
* Create a greater than or equal to (>=) field criterion
*
* @param string $fieldName The name of the field against which the value will be compared
* @param mixed $value The value for the greater than or equal to comparison
* @param string $paramName The name of the parameter to which this should be bound (optional; generated if blank)
* @return static The field with the requested criterion
*/
public static function GE(string $fieldName, mixed $value, string $paramName = ''): static
{
return new static($fieldName, Op::GE, $value, $paramName);
}
/**
* Create a less than (<) field criterion
*
* @param string $fieldName The name of the field against which the value will be compared
* @param mixed $value The value for the less than comparison
* @param string $paramName The name of the parameter to which this should be bound (optional; generated if blank)
* @return static The field with the requested criterion
*/
public static function LT(string $fieldName, mixed $value, string $paramName = ''): static
{
return new static($fieldName, Op::LT, $value, $paramName);
}
/**
* Create a less than or equal to (<=) field criterion
*
* @param string $fieldName The name of the field against which the value will be compared
* @param mixed $value The value for the less than or equal to comparison
* @param string $paramName The name of the parameter to which this should be bound (optional; generated if blank)
* @return static The field with the requested criterion
*/
public static function LE(string $fieldName, mixed $value, string $paramName = ''): static
{
return new static($fieldName, Op::LE, $value, $paramName);
}
/**
* Create a not equals (<>) field criterion
*
* @param string $fieldName The name of the field against which the value will be compared
* @param mixed $value The value for the not equals comparison
* @param string $paramName The name of the parameter to which this should be bound (optional; generated if blank)
* @return static The field with the requested criterion
*/
public static function NE(string $fieldName, mixed $value, string $paramName = ''): static
{
return new static($fieldName, Op::NE, $value, $paramName);
}
/**
* Create a BETWEEN field criterion
*
* @param string $fieldName The name of the field against which the value will be compared
* @param mixed $minValue The lower value for range
* @param mixed $maxValue The upper value for the range
* @param string $paramName The name of the parameter to which this should be bound (optional; generated if blank)
* @return static The field with the requested criterion
*/
public static function BT(string $fieldName, mixed $minValue, mixed $maxValue, string $paramName = ''): static
{
return new static($fieldName, Op::BT, [$minValue, $maxValue], $paramName);
}
/**
* Create an exists (IS NOT NULL) field criterion
*
* @param string $fieldName The name of the field for which existence will be checked
* @return static The field with the requested criterion
*/
public static function EX(string $fieldName): static
{
return new static($fieldName, Op::EX, '', '');
}
/**
* Create a not exists (IS NULL) field criterion
*
* @param string $fieldName The name of the field for which non-existence will be checked
* @return static The field with the requested criterion
*/
public static function NEX(string $fieldName): static
{
return new static($fieldName, Op::NEX, '', '');
}
}