Skip to content
This repository was archived by the owner on Jun 4, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b5bcd7a
Initial commit of this branch to create PR
SOHELAHMED7 Jan 24, 2023
6a84c06
Resolve allOf along with FK migration - WIP
SOHELAHMED7 Jan 24, 2023
4d3cbb5
Implement for hasOne
SOHELAHMED7 Jan 26, 2023
0cb0bfe
Fix style
SOHELAHMED7 Jan 27, 2023
d2eb886
WIP
SOHELAHMED7 Jan 30, 2023
f346b0b
uncomment
SOHELAHMED7 Jan 31, 2023
db1152b
Merge branch 'master' of https://github.com/SOHELAHMED7/yii2-openapi …
SOHELAHMED7 Jan 31, 2023
6f7ad6c
Merge branch 'master' of github.com:SOHELAHMED7/yii2-openapi into 131…
SOHELAHMED7 Mar 1, 2023
25f32d2
WIP
SOHELAHMED7 Mar 3, 2023
f235119
WIP
SOHELAHMED7 Mar 3, 2023
5830679
Add Implementation for https://github.com/cebe/yii2-app-api/issues/17…
SOHELAHMED7 Mar 3, 2023
0f412e1
Move major par to constructor of PropertySchema class
SOHELAHMED7 Mar 8, 2023
b5116b1
Handle the case when on delete is null but on update is not null
SOHELAHMED7 Mar 8, 2023
1b6d504
Add more tests + cleanup + refactor + add docs
SOHELAHMED7 Mar 8, 2023
01b36e3
Finish tests
SOHELAHMED7 Mar 10, 2023
e5fbd19
Merge pull request #14 from SOHELAHMED7/131-add-ability-to-add-on-del…
SOHELAHMED7 Mar 10, 2023
74b4422
Merge branch 'master' of https://github.com/SOHELAHMED7/yii2-openapi …
SOHELAHMED7 Mar 10, 2023
4051089
Add docs and enhancements for https://github.com/cebe/yii2-openapi/is…
SOHELAHMED7 Mar 10, 2023
09728e3
Merge branch 'cebe:master' into master
SOHELAHMED7 Mar 10, 2023
2a9a331
Merge branch 'master' of https://github.com/SOHELAHMED7/yii2-openapi …
SOHELAHMED7 Mar 10, 2023
6f4696a
Fix style
SOHELAHMED7 Mar 10, 2023
ad2273e
Sorting models as per relations dependencies WIP
SOHELAHMED7 Mar 16, 2023
ec2c66e
Implement PR feedback
SOHELAHMED7 Mar 16, 2023
8d51a34
Fix styles
SOHELAHMED7 Mar 16, 2023
82f04d4
Merge pull request #19 from SOHELAHMED7/131-add-ability-to-add-on-del…
SOHELAHMED7 Mar 16, 2023
1c84ee8
Sort models by relation dependencies
SOHELAHMED7 Mar 19, 2023
493aeb4
Rename variable names
SOHELAHMED7 Mar 19, 2023
43d82e0
Reflect model namespace in FakerStubResolver
SOHELAHMED7 Mar 19, 2023
0e2b3d7
WIP
SOHELAHMED7 Mar 19, 2023
61f8fba
Move sort order to yii2-app-api + make proper namespaces where needed…
SOHELAHMED7 Mar 20, 2023
a79e5f5
Adjust existing tests as per new changes in Faker generation
SOHELAHMED7 Mar 20, 2023
fb347af
Make tests stronger
SOHELAHMED7 Mar 20, 2023
91300db
Revert a change that introduce bug
SOHELAHMED7 Mar 20, 2023
21ec09c
Fix style
SOHELAHMED7 Mar 21, 2023
d9f4310
Merge pull request #18 from SOHELAHMED7/enhance-faker-to-consider-rel…
SOHELAHMED7 Mar 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,49 @@ created_at:

Also see: https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html

### `x-fk-on-delete`

Allow to set foreign key constraint in migrations for ON DELETE event of row in database table. Example:

```yaml
components:
schemas:
User:
type: object
description: x on-x (update|delete) foreign key constraint
properties:
id:
type: integer
name:
type: string
Post:
type: object
description: x on-x (update|delete) foreign key constraint
properties:
id:
type: integer
title:
type: string
user:
allOf:
- $ref: '#/components/schemas/User'
- x-fk-on-update: CASCADE
user_2:
allOf:
- $ref: '#/components/schemas/User'
- x-fk-on-update: CASCADE
- x-fk-on-delete: SET NULL
user_3:
allOf:
- $ref: '#/components/schemas/User'
- x-fk-on-delete: SET NULL
user_4:
$ref: '#/components/schemas/User' # without any constraints
```

### `x-fk-on-update`

Allow to set foreign key constraint in migrations for ON UPDATE event of row in database table. For example, see above section for `x-fk-on-delete`.

## Many-to-Many relation definition

Expand Down
17 changes: 15 additions & 2 deletions src/generator/default/faker.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ public function generateModel($attributes = [])
{
$faker = $this->faker;
$uniqueFaker = $this->uniqueFaker;
$model = new <?= $model->getClassName() ?>();
$model = new <?= $modelClass ?>();
<?php foreach ($model->attributes as $attribute):
if (!$attribute->fakerStub || $attribute->isReference()) {
if (!$attribute->fakerStub /*|| $attribute->isReference()*/) {
continue;
}
?>
Expand All @@ -62,4 +62,17 @@ public function generateModel($attributes = [])
}
return $model;
}
<?php if ($model->hasOneRelations):?>

public static function dependentOn()
{
return [
// just model class names
<?php foreach ($model->hasOneRelations as $key => $hasOneRelation): ?>
<?php echo \yii\helpers\VarDumper::export($model->hasOneRelations[$key]->getClassName()).','.PHP_EOL ?>
<?php endforeach; ?>

];
}
<?php endif;?>
}
17 changes: 13 additions & 4 deletions src/lib/AttributeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace cebe\yii2openapi\lib;

use cebe\yii2openapi\lib\Config;
use cebe\yii2openapi\lib\CustomSpecAttr;
use cebe\yii2openapi\lib\exceptions\InvalidDefinitionException;
use cebe\yii2openapi\lib\items\Attribute;
Expand Down Expand Up @@ -66,20 +67,24 @@ class AttributeResolver
*/
private $junctions;

/**@var bool */
/** @var bool */
private $isJunctionSchema;

/**@var bool */
/** @var bool */
private $hasMany2Many;

public function __construct(string $schemaName, ComponentSchema $schema, JunctionSchemas $junctions)
/** @var Config */
private $config;

public function __construct(string $schemaName, ComponentSchema $schema, JunctionSchemas $junctions, ?Config $config = null)
{
$this->schemaName = $schemaName;
$this->schema = $schema;
$this->tableName = $schema->resolveTableName($schemaName);
$this->junctions = $junctions;
$this->isJunctionSchema = $junctions->isJunctionSchema($schemaName);
$this->hasMany2Many = $junctions->hasMany2Many($schemaName);
$this->config = $config;
}

/**
Expand All @@ -90,6 +95,8 @@ public function __construct(string $schemaName, ComponentSchema $schema, Junctio
public function resolve():DbModel
{
foreach ($this->schema->getProperties() as $property) {
/** @var $property \cebe\yii2openapi\lib\openapi\PropertySchema */

$isRequired = $this->schema->isRequiredProperty($property->getName());
if ($this->isJunctionSchema) {
$this->resolveJunctionTableProperty($property, $isRequired);
Expand Down Expand Up @@ -248,6 +255,8 @@ protected function resolveProperty(PropertySchema $property, bool $isRequired):v
[$property->getName(), $relatedTableName, $relatedClassName]
)
->asHasOne([$fkProperty->getName() => $attribute->columnName]);
$relation->onUpdateFkConstraint = $property->onUpdateFkConstraint;
$relation->onDeleteFkConstraint = $property->onDeleteFkConstraint;
if ($property->isRefPointerToSelf()) {
$relation->asSelfReference();
}
Expand Down Expand Up @@ -387,7 +396,7 @@ protected function catchManyToMany(
*/
protected function guessFakerStub(Attribute $attribute, PropertySchema $property):?string
{
$resolver = Yii::createObject(['class' => FakerStubResolver::class], [$attribute, $property]);
$resolver = Yii::createObject(['class' => FakerStubResolver::class], [$attribute, $property, $this->config]);
return $resolver->resolve();
}

Expand Down
6 changes: 6 additions & 0 deletions src/lib/CustomSpecAttr.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,10 @@ class CustomSpecAttr
* @see https://github.com/cebe/yii2-openapi/blob/master/README.md#x-db-default-expression
*/
public const DB_DEFAULT_EXPRESSION = 'x-db-default-expression';

/**
* Foreign key constraints. See README for usage docs
*/
public const FK_ON_DELETE = 'x-fk-on-delete';
public const FK_ON_UPDATE = 'x-fk-on-update';
}
14 changes: 13 additions & 1 deletion src/lib/FakerStubResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@ class FakerStubResolver
*/
private $property;

public function __construct(Attribute $attribute, PropertySchema $property)
/** @var Config */
private $config;

public function __construct(Attribute $attribute, PropertySchema $property, ?Config $config = null)
{
$this->attribute = $attribute;
$this->property = $property;
$this->config = $config;
}

public function resolve():?string
Expand All @@ -46,6 +50,14 @@ public function resolve():?string
if ($this->attribute->isReadOnly() && $this->attribute->isVirtual()) {
return null;
}

// column name ends with `_id`
if (substr($this->attribute->columnName, -strlen('_id'))==='_id') {
return '$faker->randomElement(\\'.$this->config->modelNamespace
. ($this->config->modelNamespace ? '\\' : '')
. ucfirst($this->attribute->reference).'::find()->select("id")->column())';
}

$limits = $this->attribute->limits;
switch ($this->attribute->phpType) {
case 'bool':
Expand Down
2 changes: 1 addition & 1 deletion src/lib/SchemaToDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public function prepareModels():array
$schemaName = $junctions->trimPrefix($schemaName);
}
/**@var \cebe\yii2openapi\lib\AttributeResolver $resolver */
$resolver = Yii::createObject(AttributeResolver::class, [$schemaName, $schema, $junctions]);
$resolver = Yii::createObject(AttributeResolver::class, [$schemaName, $schema, $junctions, $this->config]);
$models[$schemaName] = $resolver->resolve();
}
foreach ($models as $model) {
Expand Down
3 changes: 3 additions & 0 deletions src/lib/items/AttributeRelation.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
use yii\helpers\Inflector;
use yii\helpers\VarDumper;
use function reset;
use cebe\yii2openapi\lib\traits\ForeignKeyConstraints;

class AttributeRelation
{
use ForeignKeyConstraints;

public const HAS_ONE = 'hasOne';
public const HAS_MANY = 'hasMany';

Expand Down
2 changes: 1 addition & 1 deletion src/lib/migrations/BaseMigrationBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public function buildFresh():MigrationModel
$refCol = $relation->getForeignName();
$refTable = $relation->getTableAlias();
$fkName = $this->foreignKeyName($this->model->tableName, $fkCol, $relation->getTableName(), $refCol);
$this->migration->addUpCode($builder->addFk($fkName, $tableName, $fkCol, $refTable, $refCol))
$this->migration->addUpCode($builder->addFk($fkName, $tableName, $fkCol, $refTable, $refCol, $relation->onDeleteFkConstraint, $relation->onUpdateFkConstraint))
->addDownCode($builder->dropFk($fkName, $tableName));
if ($relation->getTableName() !== $this->model->tableName) {
$this->migration->dependencies[] = $refTable;
Expand Down
23 changes: 21 additions & 2 deletions src/lib/migrations/MigrationRecordBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ final class MigrationRecordBuilder
public const ADD_ENUM = MigrationRecordBuilder::INDENT . "\$this->execute('CREATE TYPE \"enum_%s_%s\" AS ENUM(%s)');";
public const DROP_ENUM = MigrationRecordBuilder::INDENT . "\$this->execute('DROP TYPE \"enum_%s_%s\"');";
public const DROP_TABLE = MigrationRecordBuilder::INDENT . "\$this->dropTable('%s');";

public const ADD_FK = MigrationRecordBuilder::INDENT . "\$this->addForeignKey('%s', '%s', '%s', '%s', '%s');";
public const ADD_FK_WITH_JUST_ON_DELETE = MigrationRecordBuilder::INDENT . "\$this->addForeignKey('%s', '%s', '%s', '%s', '%s', '%s');";
public const ADD_FK_WITH_ON_UPDATE = MigrationRecordBuilder::INDENT . "\$this->addForeignKey('%s', '%s', '%s', '%s', '%s', %s, '%s');";

public const ADD_PK = MigrationRecordBuilder::INDENT . "\$this->addPrimaryKey('%s', '%s', '%s');";
public const ADD_COLUMN = MigrationRecordBuilder::INDENT . "\$this->addColumn('%s', '%s', %s);";
public const ALTER_COLUMN = MigrationRecordBuilder::INDENT . "\$this->alterColumn('%s', '%s', %s);";
Expand Down Expand Up @@ -205,9 +209,24 @@ public function createEnum(string $tableAlias, string $columnName, array $values
return sprintf(self::ADD_ENUM, $rawTableName, $columnName, ColumnToCode::enumToString($values));
}

public function addFk(string $fkName, string $tableAlias, string $fkCol, string $refTable, string $refCol):string
public function addFk(string $fkName, string $tableAlias, string $fkCol, string $refTable, string $refCol, ?string $onDelete = null, ?string $onUpdate = null):string
{
return sprintf(self::ADD_FK, $fkName, $tableAlias, $fkCol, $refTable, $refCol);
if ($onUpdate === null && $onDelete === null) {
return sprintf(self::ADD_FK, $fkName, $tableAlias, $fkCol, $refTable, $refCol);
} elseif ($onDelete !== null && $onUpdate === null) {
return sprintf(self::ADD_FK_WITH_JUST_ON_DELETE, $fkName, $tableAlias, $fkCol, $refTable, $refCol, $onDelete);
} elseif ($onUpdate !== null) {
return sprintf(
self::ADD_FK_WITH_ON_UPDATE,
$fkName,
$tableAlias,
$fkCol,
$refTable,
$refCol,
$onDelete === null ? 'null' : "'$onDelete'",
$onUpdate
);
}
}

public function addUniqueIndex(string $tableAlias, string $indexName, array $columns):string
Expand Down
38 changes: 32 additions & 6 deletions src/lib/openapi/PropertySchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@
use yii\helpers\VarDumper;
use function is_int;
use function strpos;
use cebe\yii2openapi\lib\traits\ForeignKeyConstraints;

class PropertySchema
{
use ForeignKeyConstraints;

public const REFERENCE_PATH = '/components/schemas/';
public const REFERENCE_PATH_LEN = 20;

Expand All @@ -40,22 +43,22 @@ class PropertySchema
*/
private $property;

/**@var string* */
/** @var string* */
private $name;

/**@var bool $isReference * */
/** @var bool $isReference * */
private $isReference = false;

/**@var bool $isItemsReference * */
/** @var bool $isItemsReference * */
private $isItemsReference = false;

/**@var bool $isNonDbReference * */
/** @var bool $isNonDbReference * */
private $isNonDbReference = false;

/**@var string $refPointer * */
/** @var string $refPointer */
private $refPointer;

/**@var \cebe\yii2openapi\lib\openapi\ComponentSchema $refSchema * */
/** @var \cebe\yii2openapi\lib\openapi\ComponentSchema $refSchema */
private $refSchema;

/**
Expand All @@ -82,6 +85,29 @@ public function __construct(SpecObjectInterface $property, string $name, Compone
$this->schema = $schema;
$this->isPk = $name === $schema->getPkName();

$onUpdate = $onDelete = $reference = null;

foreach ($property->allOf ?? [] as $element) {
if (!empty($element->{CustomSpecAttr::FK_ON_UPDATE})) {
$onUpdate = $element->{CustomSpecAttr::FK_ON_UPDATE};
}
if (!empty($element->{CustomSpecAttr::FK_ON_DELETE})) {
$onDelete = $element->{CustomSpecAttr::FK_ON_DELETE};
}
if ($element instanceof Reference) {
$reference = $element;
}
}
if (
($onUpdate !== null || $onDelete !== null) &&
($reference instanceof Reference)
) {
$this->onUpdateFkConstraint = $onUpdate;
$this->onDeleteFkConstraint = $onDelete;
$this->property = $reference;
$property = $this->property;
}

if ($property instanceof Reference) {
$this->initReference();
} elseif (
Expand Down
27 changes: 27 additions & 0 deletions src/lib/traits/ForeignKeyConstraints.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* @copyright Copyright (c) 2018 Carsten Brandt <[email protected]> and contributors
* @license https://github.com/cebe/yii2-openapi/blob/master/LICENSE
*/

namespace cebe\yii2openapi\lib\traits;

trait ForeignKeyConstraints
{
/**
* @var string
* Contains foreign key constraint
* @example 'SET NULL'
* @example 'CASCADE'
*/
public $onDeleteFkConstraint;

/**
* @var string
* Contains foreign key constraint
* @example 'SET NULL'
* @example 'CASCADE'
*/
public $onUpdateFkConstraint;
}
2 changes: 1 addition & 1 deletion tests/DbTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ protected function checkFiles(array $actual, array $expected)
self::assertFileExists($file);
self::assertFileExists($expectedFilePath);

$this->assertFileEquals($expectedFilePath, $file, "Failed asserting that file contents of\n$file\nare equal to file contents of\n$expectedFilePath");
$this->assertFileEquals($expectedFilePath, $file, "Failed asserting that file contents of\n$file\nare equal to file contents of\n$expectedFilePath \n\n cp $file $expectedFilePath \n\n ");
}
}

Expand Down
8 changes: 4 additions & 4 deletions tests/fixtures/blog.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@
->asReference('Category')
->setRequired()
->setDescription('Category of posts')
->setFakerStub('$uniqueFaker->numberBetween(0, 1000000)'),
->setFakerStub('$faker->randomElement(\Category::find()->select("id")->column())'),
'created_at' => (new Attribute('created_at', ['phpType' => 'string', 'dbType' => 'date']))
->setFakerStub('$faker->dateTimeThisCentury->format(\'Y-m-d\')'),
'created_by' => (new Attribute('created_by', ['phpType' => 'int', 'dbType' => 'integer']))
->asReference('User')
->setDescription('The User')
->setFakerStub('$uniqueFaker->numberBetween(0, 1000000)'),
->setFakerStub('$faker->randomElement(\User::find()->select("id")->column())'),
],
'relations' => [
'category' => new AttributeRelation('category',
Expand Down Expand Up @@ -110,12 +110,12 @@
->setSize(128)
->asReference('Post')
->setDescription('A blog post (uid used as pk for test purposes)')
->setFakerStub('substr($uniqueFaker->sha256, 0, 128)'),
->setFakerStub('$faker->randomElement(\Post::find()->select("id")->column())'),
'author' => (new Attribute('author', ['phpType' => 'int', 'dbType' => 'integer']))
->setRequired()
->asReference('User')
->setDescription('The User')
->setFakerStub('$uniqueFaker->numberBetween(0, 1000000)'),
->setFakerStub('$faker->randomElement(\User::find()->select("id")->column())'),
'message' => (new Attribute('message', ['phpType' => 'array', 'dbType' => 'json', 'xDbType' => 'json']))
->setRequired()->setDefault([])->setFakerStub('[]'),
'meta_data' => (new Attribute('meta_data', ['phpType' => 'array', 'dbType' => 'json', 'xDbType' => 'json']))
Expand Down
Loading