Skip to content

Commit fd6de37

Browse files
authored
Declare generated fields in ORM Schema (#31)
1 parent 891fd97 commit fd6de37

File tree

16 files changed

+155
-40
lines changed

16 files changed

+155
-40
lines changed

.github/FUNDING.yml

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# These are supported funding model platforms
2+
3+
github: cycle

.github/workflows/ci-mssql.yml

+8-5
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@ jobs:
2626
extensions: pdo, pdo_sqlsrv
2727
mssql: 'server:2019-latest'
2828
- php: '8.1'
29-
extensions: pdo, pdo_sqlsrv-5.11.0
29+
extensions: pdo, pdo_sqlsrv
3030
mssql: 'server:2019-latest'
3131
- php: '8.2'
32-
extensions: pdo, pdo_sqlsrv-5.11.0
32+
extensions: pdo, pdo_sqlsrv
33+
mssql: 'server:2019-latest'
34+
- php: '8.3'
35+
extensions: pdo, pdo_sqlsrv
3336
mssql: 'server:2019-latest'
3437

3538
services:
@@ -70,11 +73,11 @@ jobs:
7073
run: composer self-update
7174

7275
- name: Install dependencies with composer
73-
if: matrix.php != '8.2'
76+
if: matrix.php != '8.4'
7477
run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
7578

76-
- name: Install dependencies with composer php 8.2
77-
if: matrix.php == '8.2'
79+
- name: Install dependencies with composer php 8.4
80+
if: matrix.php == '8.4'
7881
run: composer update --ignore-platform-reqs --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
7982

8083
- name: Run tests with phpunit without coverage

.github/workflows/ci-mysql.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
- "8.0"
2626
- "8.1"
2727
- "8.2"
28+
- "8.3"
2829

2930
mysql-version:
3031
- "5.7"
@@ -81,11 +82,11 @@ jobs:
8182
php${{ matrix.php-version }}-composer-${{ matrix.dependencies }}-
8283
8384
- name: Install dependencies with composer
84-
if: matrix.php-version != '8.2'
85+
if: matrix.php-version != '8.4'
8586
run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
8687

87-
- name: Install dependencies with composer php 8.2
88-
if: matrix.php-version == '8.2'
88+
- name: Install dependencies with composer php 8.4
89+
if: matrix.php-version == '8.4'
8990
run: composer update --ignore-platform-reqs --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
9091

9192
- name: Run mysql tests with phpunit

.github/workflows/ci-pgsql.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ jobs:
2424
- "8.0"
2525
- "8.1"
2626
- "8.2"
27+
- "8.3"
2728

2829
pgsql-version:
2930
- "10"
@@ -82,11 +83,11 @@ jobs:
8283
php${{ matrix.php-version }}-composer-${{ matrix.dependencies }}-
8384
8485
- name: Install dependencies with composer
85-
if: matrix.php-version != '8.2'
86+
if: matrix.php-version != '8.4'
8687
run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
8788

88-
- name: Install dependencies with composer php 8.2
89-
if: matrix.php-version == '8.2'
89+
- name: Install dependencies with composer php 8.4
90+
if: matrix.php-version == '8.4'
9091
run: composer update --ignore-platform-reqs --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
9192

9293
- name: Run pgsql tests with phpunit

.github/workflows/main.yml

+8-6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121
- "8.0"
2222
- "8.1"
2323
- "8.2"
24+
- "8.3"
2425
steps:
2526
- name: Checkout
2627
uses: actions/checkout@v2
@@ -46,10 +47,10 @@ jobs:
4647
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
4748
restore-keys: ${{ runner.os }}-composer-
4849
- name: Install dependencies with composer
49-
if: matrix.php-version != '8.2'
50+
if: matrix.php-version != '8.4'
5051
run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
51-
- name: Install dependencies with composer php 8.2
52-
if: matrix.php-version == '8.2'
52+
- name: Install dependencies with composer php 8.4
53+
if: matrix.php-version == '8.4'
5354
run: composer update --ignore-platform-reqs --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
5455
- name: Execute Tests
5556
run: |
@@ -78,6 +79,7 @@ jobs:
7879
- "8.0"
7980
- "8.1"
8081
- "8.2"
82+
- "8.3"
8183
steps:
8284
- name: Checkout
8385
uses: actions/checkout@v2
@@ -99,11 +101,11 @@ jobs:
99101
restore-keys: ${{ runner.os }}-composer-
100102

101103
- name: Install dependencies with composer
102-
if: matrix.php-version != '8.1'
104+
if: matrix.php-version != '8.4'
103105
run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
104106

105-
- name: Install dependencies with composer php 8.1
106-
if: matrix.php-version == '8.1'
107+
- name: Install dependencies with composer php 8.4
108+
if: matrix.php-version == '8.4'
107109
run: composer update --ignore-platform-reqs --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi
108110

109111
- name: Execute Tests

.github/workflows/static.yml

-2
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,3 @@ jobs:
1212
with:
1313
os: >-
1414
['ubuntu-latest']
15-
php: >-
16-
['8.1']

composer.json

+34-3
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,43 @@
22
"name": "cycle/entity-behavior",
33
"description": "Provides a collection of attributes that add behaviors to Cycle ORM entities",
44
"type": "library",
5+
"license": "MIT",
6+
"homepage": "https://cycle-orm.dev",
7+
"support": {
8+
"issues": "https://github.com/cycle/entity-behavior/issues",
9+
"source": "https://github.com/cycle/entity-behavior",
10+
"docs": "https://cycle-orm.dev/docs",
11+
"chat": "https://discord.gg/spiralphp"
12+
},
13+
"authors": [
14+
{
15+
"name": "Anton Titov (wolfy-j)",
16+
"email": "[email protected]"
17+
},
18+
{
19+
"name": "Aleksei Gagarin (roxblnfk)",
20+
"email": "[email protected]"
21+
},
22+
{
23+
"name": "Pavel Butchnev (butschster)",
24+
"email": "[email protected]"
25+
},
26+
{
27+
"name": "Maksim Smakouz (msmakouz)",
28+
"email": "[email protected]"
29+
}
30+
],
31+
"funding": [
32+
{
33+
"type": "github",
34+
"url": "https://github.com/sponsors/cycle"
35+
}
36+
],
537
"require": {
638
"php": ">=8.0",
739
"psr/event-dispatcher": "^1",
8-
"cycle/orm": "^2.0",
9-
"cycle/schema-builder": "^2.5",
40+
"cycle/orm": "^2.7",
41+
"cycle/schema-builder": "^2.8",
1042
"psr/container": "^1.0|^2.0",
1143
"yiisoft/injector": "^1.0"
1244
},
@@ -17,7 +49,6 @@
1749
"spiral/tokenizer": "^2.8 || ^3.0",
1850
"vimeo/psalm": "^5.11"
1951
},
20-
"license": "MIT",
2152
"autoload": {
2253
"psr-4": {
2354
"Cycle\\ORM\\Entity\\Behavior\\": "src/"

src/CreatedAt.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Cycle\ORM\Entity\Behavior\Schema\BaseModifier;
99
use Cycle\ORM\Entity\Behavior\Schema\RegistryModifier;
1010
use Cycle\ORM\Entity\Behavior\Listener\CreatedAt as Listener;
11+
use Cycle\ORM\Schema\GeneratedField;
1112
use Cycle\Schema\Registry;
1213
use Doctrine\Common\Annotations\Annotation\Attribute;
1314
use Doctrine\Common\Annotations\Annotation\Attributes;
@@ -63,7 +64,7 @@ public function compute(Registry $registry): void
6364
$this->column = $modifier->findColumnName($this->field, $this->column);
6465

6566
if ($this->column !== null) {
66-
$modifier->addDatetimeColumn($this->column, $this->field)
67+
$modifier->addDatetimeColumn($this->column, $this->field, GeneratedField::BEFORE_INSERT)
6768
->nullable(false)
6869
->defaultValue(AbstractColumn::DATETIME_NOW);
6970
}
@@ -75,7 +76,7 @@ public function render(Registry $registry): void
7576

7677
$this->column = $modifier->findColumnName($this->field, $this->column) ?? $this->field;
7778

78-
$modifier->addDatetimeColumn($this->column, $this->field)
79+
$modifier->addDatetimeColumn($this->column, $this->field, GeneratedField::BEFORE_INSERT)
7980
->nullable(false)
8081
->defaultValue(AbstractColumn::DATETIME_NOW);
8182
}

src/OptimisticLock.php

+18-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Cycle\ORM\Entity\Behavior\Schema\RegistryModifier;
99
use Cycle\ORM\Entity\Behavior\Exception\BehaviorCompilationException;
1010
use Cycle\ORM\Entity\Behavior\Listener\OptimisticLock as Listener;
11+
use Cycle\ORM\Schema\GeneratedField;
1112
use Cycle\Schema\Definition\Field;
1213
use Cycle\Schema\Registry;
1314
use Doctrine\Common\Annotations\Annotation\Enum;
@@ -132,18 +133,32 @@ private function addField(Registry $registry): void
132133

133134
switch ($this->rule) {
134135
case self::RULE_INCREMENT:
135-
$modifier->addIntegerColumn($this->column, $this->field)
136+
$modifier
137+
->addIntegerColumn(
138+
$this->column,
139+
$this->field,
140+
GeneratedField::BEFORE_INSERT | GeneratedField::BEFORE_UPDATE
141+
)
136142
->nullable(false)
137143
->defaultValue(self::DEFAULT_INT_VERSION);
138144
break;
139145
case self::RULE_RAND_STR:
140146
case self::RULE_MICROTIME:
141-
$modifier->addStringColumn($this->column, $this->field)
147+
$modifier
148+
->addStringColumn(
149+
$this->column,
150+
$this->field,
151+
GeneratedField::BEFORE_INSERT | GeneratedField::BEFORE_UPDATE
152+
)
142153
->nullable(false)
143154
->string(self::STRING_COLUMN_LENGTH);
144155
break;
145156
case self::RULE_DATETIME:
146-
$modifier->addDatetimeColumn($this->column, $this->field);
157+
$modifier->addDatetimeColumn(
158+
$this->column,
159+
$this->field,
160+
GeneratedField::BEFORE_INSERT | GeneratedField::BEFORE_UPDATE
161+
);
147162
break;
148163
default:
149164
throw new BehaviorCompilationException(

src/Schema/RegistryModifier.php

+24-11
Original file line numberDiff line numberDiff line change
@@ -51,72 +51,85 @@ public function __construct(Registry $registry, string $role)
5151
$this->defaults = $registry->getDefaults();
5252
}
5353

54-
public function addDatetimeColumn(string $columnName, string $fieldName): AbstractColumn
54+
public function addDatetimeColumn(string $columnName, string $fieldName, int|null $generated = null): AbstractColumn
5555
{
5656
if ($this->fields->has($fieldName)) {
5757
if (!static::isDatetimeType($this->fields->get($fieldName)->getType())) {
5858
throw new BehaviorCompilationException(sprintf('Field %s must be of type datetime.', $fieldName));
5959
}
6060
$this->validateColumnName($fieldName, $columnName);
61+
$this->fields->get($fieldName)->setGenerated($generated);
6162

6263
return $this->table->column($columnName);
6364
}
6465

65-
$this->fields->set(
66-
$fieldName,
67-
(new Field())->setColumn($columnName)->setType('datetime')->setTypecast('datetime')
68-
);
66+
$field = (new Field())
67+
->setColumn($columnName)
68+
->setType('datetime')
69+
->setTypecast('datetime')
70+
->setGenerated($generated);
71+
$this->fields->set($fieldName, $field);
6972

7073
return $this->table->column($columnName)->type(self::DATETIME_COLUMN);
7174
}
7275

73-
public function addIntegerColumn(string $columnName, string $fieldName): AbstractColumn
76+
public function addIntegerColumn(string $columnName, string $fieldName, int|null $generated = null): AbstractColumn
7477
{
7578
if ($this->fields->has($fieldName)) {
7679
if (!static::isIntegerType($this->fields->get($fieldName)->getType())) {
7780
throw new BehaviorCompilationException(sprintf('Field %s must be of type integer.', $fieldName));
7881
}
7982
$this->validateColumnName($fieldName, $columnName);
83+
$this->fields->get($fieldName)->setGenerated($generated);
8084

8185
return $this->table->column($columnName);
8286
}
8387

84-
$this->fields->set($fieldName, (new Field())->setColumn($columnName)->setType('integer')->setTypecast('int'));
88+
$field = (new Field())
89+
->setColumn($columnName)
90+
->setType('integer')
91+
->setTypecast('int')
92+
->setGenerated($generated);
93+
$this->fields->set($fieldName, $field);
8594

8695
return $this->table->column($columnName)->type(self::INT_COLUMN);
8796
}
8897

89-
public function addStringColumn(string $columnName, string $fieldName): AbstractColumn
98+
public function addStringColumn(string $columnName, string $fieldName, int|null $generated = null): AbstractColumn
9099
{
91100
if ($this->fields->has($fieldName)) {
92101
if (!static::isStringType($this->fields->get($fieldName)->getType())) {
93102
throw new BehaviorCompilationException(sprintf('Field %s must be of type string.', $fieldName));
94103
}
95104
$this->validateColumnName($fieldName, $columnName);
105+
$this->fields->get($fieldName)->setGenerated($generated);
96106

97107
return $this->table->column($columnName);
98108
}
99109

100-
$this->fields->set($fieldName, (new Field())->setColumn($columnName)->setType('string'));
110+
$field = (new Field())->setColumn($columnName)->setType('string')->setGenerated($generated);
111+
$this->fields->set($fieldName, $field);
101112

102113
return $this->table->column($columnName)->type(self::STRING_COLUMN);
103114
}
104115

105116
/**
106117
* @throws BehaviorCompilationException
107118
*/
108-
public function addUuidColumn(string $columnName, string $fieldName): AbstractColumn
119+
public function addUuidColumn(string $columnName, string $fieldName, int|null $generated = null): AbstractColumn
109120
{
110121
if ($this->fields->has($fieldName)) {
111122
if (!static::isUuidType($this->fields->get($fieldName)->getType())) {
112123
throw new BehaviorCompilationException(sprintf('Field %s must be of type uuid.', $fieldName));
113124
}
114125
$this->validateColumnName($fieldName, $columnName);
126+
$this->fields->get($fieldName)->setGenerated($generated);
115127

116128
return $this->table->column($columnName);
117129
}
118130

119-
$this->fields->set($fieldName, (new Field())->setColumn($columnName)->setType('uuid'));
131+
$field = (new Field())->setColumn($columnName)->setType('uuid')->setGenerated($generated);
132+
$this->fields->set($fieldName, $field);
120133

121134
return $this->table->column($columnName)->type(self::UUID_COLUMN);
122135
}

src/SoftDelete.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Cycle\ORM\Entity\Behavior\Schema\BaseModifier;
88
use Cycle\ORM\Entity\Behavior\Schema\RegistryModifier;
99
use Cycle\ORM\Entity\Behavior\Listener\SoftDelete as Listener;
10+
use Cycle\ORM\Schema\GeneratedField;
1011
use Cycle\Schema\Registry;
1112
use Doctrine\Common\Annotations\Annotation\Attribute;
1213
use Doctrine\Common\Annotations\Annotation\Attributes;
@@ -76,7 +77,7 @@ public function render(Registry $registry): void
7677

7778
$this->column = $modifier->findColumnName($this->field, $this->column) ?? $this->field;
7879

79-
$modifier->addDatetimeColumn($this->column, $this->field)
80+
$modifier->addDatetimeColumn($this->column, $this->field, GeneratedField::BEFORE_UPDATE)
8081
->nullable(true);
8182
}
8283
}

src/UpdatedAt.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Cycle\ORM\Entity\Behavior\Schema\BaseModifier;
88
use Cycle\ORM\Entity\Behavior\Schema\RegistryModifier;
99
use Cycle\ORM\Entity\Behavior\Listener\UpdatedAt as Listener;
10+
use Cycle\ORM\Schema\GeneratedField;
1011
use Cycle\Schema\Registry;
1112
use Doctrine\Common\Annotations\Annotation\Attribute;
1213
use Doctrine\Common\Annotations\Annotation\Attributes;
@@ -76,6 +77,10 @@ public function render(Registry $registry): void
7677

7778
$this->column = $modifier->findColumnName($this->field, $this->column) ?? $this->field;
7879

79-
$modifier->addDatetimeColumn($this->column, $this->field);
80+
$modifier->addDatetimeColumn(
81+
$this->column,
82+
$this->field,
83+
GeneratedField::BEFORE_INSERT | GeneratedField::BEFORE_UPDATE
84+
);
8085
}
8186
}

0 commit comments

Comments
 (0)