src/Field/SqlExpressionField.php
<?php
declare(strict_types=1);
namespace Atk4\Data\Field;
use Atk4\Core\InitializerTrait;
use Atk4\Data\Field;
use Atk4\Data\Model;
use Atk4\Data\Persistence\Sql\Expression;
use Atk4\Data\Persistence\Sql\Expressionable;
use Atk4\Data\Reference;
class SqlExpressionField extends Field
{
use InitializerTrait {
init as private _init;
}
public bool $neverSave = true;
public bool $readOnly = true;
/** @var \Closure<T of Model>(T, Expression): (string|Expressionable)|string|Expressionable Used expression. */
public $expr;
/** @var string Specifies how to aggregate this. */
public $aggregate;
/** @var string */
public $concatSeparator;
/** @var Reference\HasMany|null When defining as aggregate, this will point to relation object. */
public $aggregateRelation;
/** @var string Specifies which field to use. */
public $field;
#[\Override]
public function useAlias(): bool
{
return true;
}
#[\Override]
public function getDsqlExpression(Expression $expression): Expression
{
$expr = $this->expr;
if ($expr instanceof \Closure) {
$expr = $expr($this->getOwner(), $expression);
}
if (is_string($expr)) {
// if our Model has expr() method (inherited from Persistence\Sql) then use it
if ($this->getOwner()->hasMethod('expr')) {
return $this->getOwner()->expr('([])', [$this->getOwner()->expr($expr)]);
}
// otherwise call it from expression itself
return $expression->expr('([])', [$expression->expr($expr)]);
} elseif ($expr instanceof Expressionable && !$expr instanceof Expression) { // @phpstan-ignore instanceof.alwaysTrue
return $expression->expr('[]', [$expr]);
}
return $expr;
}
#[\Override]
public function __debugInfo(): array
{
return array_merge(parent::__debugInfo(), [
'expr' => $this->expr,
]);
}
}