1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace Atk4\Data\Field;
6:
7: use Atk4\Core\InitializerTrait;
8: use Atk4\Data\Field;
9: use Atk4\Data\Model;
10: use Atk4\Data\Persistence\Sql\Expression;
11: use Atk4\Data\Persistence\Sql\Expressionable;
12: use Atk4\Data\Reference;
13:
14: class SqlExpressionField extends Field
15: {
16: use InitializerTrait {
17: init as private _init;
18: }
19:
20: public bool $neverSave = true;
21: public bool $readOnly = true;
22:
23: /** @var \Closure(object, Expression): (string|Expressionable)|string|Expressionable Used expression. */
24: public $expr;
25:
26: /** @var string Specifies how to aggregate this. */
27: public $aggregate;
28:
29: /** @var string */
30: public $concatSeparator;
31:
32: /** @var Reference\HasMany|null When defining as aggregate, this will point to relation object. */
33: public $aggregateRelation;
34:
35: /** @var string Specifies which field to use. */
36: public $field;
37:
38: #[\Override]
39: public function useAlias(): bool
40: {
41: return true;
42: }
43:
44: #[\Override]
45: public function getDsqlExpression(Expression $expression): Expression
46: {
47: $expr = $this->expr;
48: if ($expr instanceof \Closure) {
49: $expr = $expr($this->getOwner(), $expression);
50: }
51:
52: if (is_string($expr)) {
53: // if our Model has expr() method (inherited from Persistence\Sql) then use it
54: if ($this->getOwner()->hasMethod('expr')) {
55: return $this->getOwner()->expr('([])', [$this->getOwner()->expr($expr)]);
56: }
57:
58: // otherwise call it from expression itself
59: return $expression->expr('([])', [$expression->expr($expr)]);
60: } elseif ($expr instanceof Expressionable && !$expr instanceof Expression) { // @phpstan-ignore-line
61: return $expression->expr('[]', [$expr]);
62: }
63:
64: return $expr;
65: }
66: }
67: