Skip to content
This repository was archived by the owner on Jun 4, 2024. It is now read-only.

Resolve multiple issues #177

Merged
merged 25 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f7c2b5b
Initial commit to create PR
SOHELAHMED7 May 28, 2024
f41f0fa
Undo initial commit
SOHELAHMED7 May 28, 2024
58b7fc3
Merge branch 'master' of github.com:SOHELAHMED7/yii2-openapi into 175…
SOHELAHMED7 May 28, 2024
51875cb
Add docs for https://github.com/cebe/yii2-openapi/issues/173
SOHELAHMED7 May 28, 2024
949a32f
Fix https://github.com/cebe/yii2-openapi/issues/175
SOHELAHMED7 May 28, 2024
fe3cd36
Merge pull request #36 from SOHELAHMED7/175-bug-allof-with-multiple-d…
SOHELAHMED7 May 28, 2024
944ee58
Initial commit to create PR
SOHELAHMED7 May 28, 2024
e42e3f2
Fix https://github.com/cebe/yii2-openapi/issues/172
SOHELAHMED7 May 29, 2024
b752fad
Refactor
SOHELAHMED7 May 29, 2024
f51c54c
Merge pull request #37 from SOHELAHMED7/172-schemayaml-requestbody-ha…
SOHELAHMED7 May 29, 2024
6d92585
IC
SOHELAHMED7 May 29, 2024
50f5ed1
Merge branch 'cebe:master' into master
SOHELAHMED7 May 29, 2024
0c77d42
Merge branches 'master' and '159-bug-giiapi-generated-rules-emailid' …
SOHELAHMED7 May 29, 2024
58811f2
Create failing test case - WIP
SOHELAHMED7 May 29, 2024
ed97a31
Fix https://github.com/cebe/yii2-openapi/issues/159
SOHELAHMED7 May 30, 2024
9c4b921
Fix style
SOHELAHMED7 May 30, 2024
4e77f4d
Merge pull request #39 from SOHELAHMED7/159-bug-giiapi-generated-rule…
SOHELAHMED7 May 30, 2024
2bed3ca
IC
SOHELAHMED7 May 30, 2024
c3c07e7
Merge branches 'master' and '158-bug-giiapi-generated-rules-enum-with…
SOHELAHMED7 May 30, 2024
01846a8
Fix https://github.com/cebe/yii2-openapi/issues/158
SOHELAHMED7 May 30, 2024
a56c90e
Merge pull request #40 from SOHELAHMED7/158-bug-giiapi-generated-rule…
SOHELAHMED7 May 30, 2024
404642a
IC
SOHELAHMED7 May 30, 2024
8a85797
Merge branches 'master' and '178-remove-php-72-and-73-from-github-act…
SOHELAHMED7 May 30, 2024
635f55f
Fix https://github.com/cebe/yii2-openapi/issues/178
SOHELAHMED7 May 30, 2024
cbae5c5
Merge pull request #41 from SOHELAHMED7/178-remove-php-72-and-73-from…
SOHELAHMED7 May 30, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
php-versions: ['7.4', '8.0', '8.1', '8.2', '8.3']

# TODO use cache
steps:
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ Such values are not allowed:
- `int null default null after low_price` (null and default will be handled by `nullable` and `default` keys respectively)
- MEDIUMINT(10) UNSIGNED ZEROFILL NULL DEFAULT '7' COMMENT 'comment' AFTER `seti`, ADD INDEX `t` (`w`)

If `enum` and `x-db-type` both are provided then for database column schema (migrations), only `x-db-type` will be considered ignoring `enum`.

### `x-indexes`

Specify table indexes
Expand Down Expand Up @@ -446,6 +448,8 @@ It works on all 3 DB: MySQL, MariaDb and PgSQL.

Note: Changes in enum values are not very simple. For Mysql and Mariadb, migrations will be generated but in many cases custom modification in it are required. For Pgsql migrations for change in enum values will not be generated. It should be handled manually.

It will be ignored for database column schema (migrations) if `x-db-type` is provided.

## Handling of `numeric` (#numeric, #MariaDb)

precision-default = 10
Expand Down
7 changes: 5 additions & 2 deletions src/lib/ValidationRulesBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ private function addRulesByAttributeName(Attribute $attribute):void
'~(url|site|website|href|link)~i' => 'url',
];
foreach ($patterns as $pattern => $validator) {
if (preg_match($pattern, strtolower($attribute->columnName))) {
if (empty($attribute->reference) # ignore column name based rules in case of reference/relation # https://github.com/cebe/yii2-openapi/issues/159
&& preg_match($pattern, strtolower($attribute->columnName))) {
$key = $attribute->columnName . '_' . $validator;
$this->rules[$key] = new ValidationRule([$attribute->columnName], $validator);
return;
Expand Down Expand Up @@ -232,7 +233,9 @@ private function prepareTypeScope():void
$this->typeScope['required'][$attribute->columnName] = $attribute->columnName;
}

if ($attribute->phpType === 'string') {
if ($attribute->phpType === 'string' &&
empty($attribute->enumValues) # don't apply trim on enum columns # https://github.com/cebe/yii2-openapi/issues/158
) {
$this->typeScope['trim'][$attribute->columnName] = $attribute->columnName;
}

Expand Down
54 changes: 32 additions & 22 deletions src/lib/openapi/ResponseSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace cebe\yii2openapi\lib\openapi;

use cebe\openapi\exceptions\UnresolvableReferenceException;
use cebe\openapi\spec\MediaType;
use cebe\openapi\spec\Operation;
use cebe\openapi\spec\Reference;
Expand Down Expand Up @@ -36,10 +37,10 @@ protected static function isObjectSchema($schema): bool
protected static function isArraySchemaWithRefItems($schema): bool
{
return isset($schema->items) && $schema->items instanceof Reference &&
(isset($schema->type) && $schema->type === 'array');
(isset($schema->type) && $schema->type === 'array');
}

protected static function hasAttributesReference($schema):bool
protected static function hasAttributesReference($schema): bool
{
return isset($schema->properties['attributes']) && $schema->properties['attributes'] instanceof Reference;
}
Expand All @@ -49,17 +50,20 @@ protected static function schemaNameByRef($schemaOrReference): ?string
// if($schemaOrReference instanceof Reference){
// $schemaOrReference->resolve();
// }
if (!$schemaOrReference instanceof Reference) { # https://github.com/cebe/yii2-openapi/issues/175
return null;
}
$ref = $schemaOrReference->getJsonReference()->getJsonPointer()->getPointer();
$name = strpos($ref, '/components/schemas/') === 0 ? substr($ref, 20) : null;
return str_replace(JunctionSchemas::PREFIX, '', $name);
}

/**
* @param \cebe\openapi\spec\Operation $operation
* @param Operation $operation
* @return array
* @throws \cebe\openapi\exceptions\UnresolvableReferenceException
* @throws UnresolvableReferenceException
*/
public static function guessResponseRelations(Operation $operation):array
public static function guessResponseRelations(Operation $operation): array
{
if (!isset($operation->responses)) {
return [];
Expand Down Expand Up @@ -109,12 +113,12 @@ public static function guessResponseRelations(Operation $operation):array
}

/**
* @param \cebe\openapi\spec\Operation $operation
* @param Operation $operation
* @param $actionType
* @return string|null
* @throws \cebe\openapi\exceptions\UnresolvableReferenceException
* @throws UnresolvableReferenceException
*/
public static function guessModelClass(Operation $operation, $actionType):?string
public static function guessModelClass(Operation $operation, $actionType): ?string
{
// first, check request body
$requestBody = $operation->requestBody;
Expand Down Expand Up @@ -159,20 +163,26 @@ public static function guessModelClass(Operation $operation, $actionType):?strin
}

/**
* @param \cebe\openapi\SpecObjectInterface $property
* @param SpecObjectInterface $property
* @return array|null[]
* @throws \cebe\openapi\exceptions\UnresolvableReferenceException
* @throws UnresolvableReferenceException
*/
public static function guessModelClassFromJsonResource(SpecObjectInterface $property): array
{
$schema = $property instanceof Reference? $property->resolve() : $property;

if (self::isObjectSchema($schema) && self::hasAttributesReference($schema)) {
$name = self::schemaNameByRef($schema->properties['attributes']);
if ($name !== null) {
return [$name, '', '', 'object'];
$schema = $property instanceof Reference ? $property->resolve() : $property;
if (self::isObjectSchema($schema)) {
if (self::hasAttributesReference($schema)) {
$name = self::schemaNameByRef($schema->properties['attributes']);
if ($name !== null) {
return [$name, '', '', 'object'];
}
return [null, null, null, null];
} else { # https://github.com/cebe/yii2-openapi/issues/172
$name = self::schemaNameByRef($property);
if ($name !== null) {
return [$name, '', '', 'object'];
}
}
return [null, null, null, null];
}
if (self::isArraySchemaWithRefItems($property)) {
$ref = $property->items->resolve();
Expand All @@ -188,11 +198,11 @@ public static function guessModelClassFromJsonResource(SpecObjectInterface $prop
}

/**
* @param \cebe\openapi\spec\MediaType $content
* @param MediaType $content
* @return array|null[]
* @throws \cebe\openapi\exceptions\UnresolvableReferenceException
* @throws UnresolvableReferenceException
*/
public static function guessModelClassFromContent(MediaType $content):array
public static function guessModelClassFromContent(MediaType $content): array
{
/** @var $referencedSchema Schema */
if ($content->schema instanceof Reference) {
Expand Down Expand Up @@ -255,9 +265,9 @@ public static function guessModelClassFromContent(MediaType $content):array
* @param Operation $operation
* @param $modelClass
* @return null|array
* @throws \cebe\openapi\exceptions\UnresolvableReferenceException
* @throws UnresolvableReferenceException
*/
public static function findResponseWrapper(Operation $operation, $modelClass):?array
public static function findResponseWrapper(Operation $operation, $modelClass): ?array
{
if (!isset($operation->responses)) {
return null;
Expand Down
2 changes: 1 addition & 1 deletion tests/specs/blog_v2/models/base/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static function tableName()
public function rules()
{
return [
'trim' => [['title', 'slug', 'lang', 'created_at'], 'trim'],
'trim' => [['title', 'slug', 'created_at'], 'trim'],
'required' => [['title', 'category_id', 'active'], 'required'],
'category_id_integer' => [['category_id'], 'integer'],
'category_id_exist' => [['category_id'], 'exist', 'targetRelation' => 'Category'],
Expand Down
2 changes: 1 addition & 1 deletion tests/specs/blog_v2/models/base/Tag.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static function tableName()
public function rules()
{
return [
'trim' => [['name', 'lang'], 'trim'],
'trim' => [['name'], 'trim'],
'required' => [['name', 'lang'], 'required'],
'name_unique' => [['name'], 'unique'],
'name_string' => [['name'], 'string', 'max' => 100],
Expand Down
2 changes: 1 addition & 1 deletion tests/specs/blog_v2/models/base/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static function tableName()
public function rules()
{
return [
'trim' => [['login', 'email', 'password', 'role', 'created_at'], 'trim'],
'trim' => [['login', 'email', 'password', 'created_at'], 'trim'],
'required' => [['login', 'email', 'password'], 'required'],
'login_unique' => [['login'], 'unique'],
'email_unique' => [['email'], 'unique'],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

return [
'openApiPath' => '@specs/issue_fix/158_bug_giiapi_generated_rules_enum_with_trim/index.yaml',
'generateUrls' => false,
'generateModels' => true,
'excludeModels' => [
'Error',
],
'generateControllers' => false,
'generateMigrations' => false,
'generateModelFaker' => true, // `generateModels` must be `true` in orde to use `generateModelFaker` as `true`
];

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

openapi: 3.0.3

info:
title: 'Proxy-Service'
version: 1.0.0

components:

schemas:

Mailing:
description: Mailing
type: object
required:
- id
- name
properties:
id:
type: integer
readOnly: true
name:
description: name
type: string
maxLength: 128
paymentMethodName:
type: string
enum:
- card
- cash
- ewallet

paths:
'/':
get:
operationId: opId
summary: summary
responses:
'200':
description: OK
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?php

namespace app\models;

use Faker\Factory as FakerFactory;
use Faker\Generator;
use Faker\UniqueGenerator;

/**
* Base fake data generator
*/
abstract class BaseModelFaker
{
/**
* @var Generator
*/
protected $faker;
/**
* @var UniqueGenerator
*/
protected $uniqueFaker;

public function __construct()
{
$this->faker = FakerFactory::create(str_replace('-', '_', \Yii::$app->language));
$this->uniqueFaker = new UniqueGenerator($this->faker);
}

abstract public function generateModel($attributes = []);

public function getFaker():Generator
{
return $this->faker;
}

public function getUniqueFaker():UniqueGenerator
{
return $this->uniqueFaker;
}

public function setFaker(Generator $faker):void
{
$this->faker = $faker;
}

public function setUniqueFaker(UniqueGenerator $faker):void
{
$this->uniqueFaker = $faker;
}

/**
* Generate and return model
* @param array|callable $attributes
* @param UniqueGenerator|null $uniqueFaker
* @return \yii\db\ActiveRecord
* @example MyFaker::makeOne(['user_id' => 1, 'title' => 'foo']);
* @example MyFaker::makeOne( function($model, $faker) {
* $model->scenario = 'create';
* $model->setAttributes(['user_id' => 1, 'title' => $faker->sentence]);
* return $model;
* });
*/
public static function makeOne($attributes = [], ?UniqueGenerator $uniqueFaker = null)
{
$fakeBuilder = new static();
if ($uniqueFaker !== null) {
$fakeBuilder->setUniqueFaker($uniqueFaker);
}
$model = $fakeBuilder->generateModel($attributes);
return $model;
}

/**
* Generate, save and return model
* @param array|callable $attributes
* @param UniqueGenerator|null $uniqueFaker
* @return \yii\db\ActiveRecord
* @example MyFaker::saveOne(['user_id' => 1, 'title' => 'foo']);
* @example MyFaker::saveOne( function($model, $faker) {
* $model->scenario = 'create';
* $model->setAttributes(['user_id' => 1, 'title' => $faker->sentence]);
* return $model;
* });
*/
public static function saveOne($attributes = [], ?UniqueGenerator $uniqueFaker = null)
{
$model = static::makeOne($attributes, $uniqueFaker);
$model->save();
return $model;
}

/**
* Generate and return multiple models
* @param int $number
* @param array|callable $commonAttributes
* @return \yii\db\ActiveRecord[]|array
* @example TaskFaker::make(5, ['project_id'=>1, 'user_id' => 2]);
* @example TaskFaker::make(5, function($model, $faker, $uniqueFaker) {
* $model->setAttributes(['name' => $uniqueFaker->username, 'state'=>$faker->boolean(20)]);
* return $model;
* });
*/
public static function make(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null):array
{
if ($number < 1) {
return [];
}
$fakeBuilder = new static();
if ($uniqueFaker !== null) {
$fakeBuilder->setUniqueFaker($uniqueFaker);
}
return array_map(function () use ($commonAttributes, $fakeBuilder) {
$model = $fakeBuilder->generateModel($commonAttributes);
return $model;
}, range(0, $number -1));
}

/**
* Generate, save and return multiple models
* @param int $number
* @param array|callable $commonAttributes
* @return \yii\db\ActiveRecord[]|array
* @example TaskFaker::save(5, ['project_id'=>1, 'user_id' => 2]);
* @example TaskFaker::save(5, function($model, $faker, $uniqueFaker) {
* $model->setAttributes(['name' => $uniqueFaker->username, 'state'=>$faker->boolean(20)]);
* return $model;
* });
*/
public static function save(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null):array
{
if ($number < 1) {
return [];
}
$fakeBuilder = new static();
if ($uniqueFaker !== null) {
$fakeBuilder->setUniqueFaker($uniqueFaker);
}
return array_map(function () use ($commonAttributes, $fakeBuilder) {
$model = $fakeBuilder->generateModel($commonAttributes);
$model->save();
return $model;
}, range(0, $number -1));
}
}
Loading
Loading