Skip to content
Merged
4 changes: 2 additions & 2 deletions src/lib/SchemaToDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public function prepareModels(): array

$openApi = $this->config->getOpenApi();
$junctions = $this->findJunctionSchemas();
foreach ($openApi->components->schemas as $schemaName => $openApiSchema) {
foreach ($openApi->components->schemas ?? [] as $schemaName => $openApiSchema) {
$schema = Yii::createObject(ComponentSchema::class, [$openApiSchema, $schemaName]);

if (!$this->canGenerateModel($schemaName, $schema)) {
Expand Down Expand Up @@ -153,7 +153,7 @@ public function findJunctionSchemas(): JunctionSchemas
{
$junctions = [];
$openApi = $this->config->getOpenApi();
foreach ($openApi->components->schemas as $schemaName => $openApiSchema) {
foreach ($openApi->components->schemas ?? [] as $schemaName => $openApiSchema) {
/**@var ComponentSchema $schema */
$schema = Yii::createObject(ComponentSchema::class, [$openApiSchema, $schemaName]);
if ($schema->isNonDb()) {
Expand Down
22 changes: 19 additions & 3 deletions src/lib/generators/ControllersGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function generate():CodeFiles
$controllerPath = $path;
/**
* @var RestAction|FractalAction $action
**/
**/
$action = $actions[0];
if ($action->prefix && !empty($action->prefixSettings)) {
$controllerNamespace = trim($action->prefixSettings['namespace'], '\\');
Expand Down Expand Up @@ -126,15 +126,31 @@ protected function makeCustomController(
];
$reflection->addMethod('checkAccess', $params, AbstractMemberGenerator::FLAG_PUBLIC, '//TODO implement checkAccess');
foreach ($abstractActions as $action) {
$responseHttpStatusCodes = '';
foreach ($this->config->getOpenApi()->paths->getPaths()[$action->urlPath]->getOperations() as $verb => $operation) {
$codes = array_keys($operation->responses->getResponses());

$only200OrDefault = false;
if ($codes === [200] || $codes === ['default']) {
$only200OrDefault = true;
}
if (in_array('default', $codes) && in_array(200, $codes) && count($codes) === 2) {
$only200OrDefault = true;
}

if ($verb === strtolower($action->requestMethod) && !$only200OrDefault) {
$responseHttpStatusCodes = implode(', ', $codes);
}
}

$params = array_map(static function ($param) {
return ['name' => $param];
}, $action->getParamNames());

$reflection->addMethod(
$action->actionMethodName,
$params,
AbstractMemberGenerator::FLAG_PUBLIC,
'//TODO implement ' . $action->actionMethodName
'//TODO implement ' . $action->actionMethodName . ($responseHttpStatusCodes ? PHP_EOL . '// In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: ' . $responseHttpStatusCodes : '')
);
}
$classFileGenerator->setClasses([$reflection]);
Expand Down
2 changes: 2 additions & 0 deletions tests/specs/blog_v2/controllers/CommentController.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public function actionListForPost($postId)
public function actionCreateForPost($postId)
{
//TODO implement actionCreateForPost
// In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 201, default
}

public function actionViewForPost($slug, $id)
Expand All @@ -28,6 +29,7 @@ public function actionViewForPost($slug, $id)
public function actionDeleteForPost($slug, $id)
{
//TODO implement actionDeleteForPost
// In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 204
}

public function actionUpdateForPost($slug, $id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ public function checkAccess($action, $model = null, $params = [])
public function actionListForAccount($accountId)
{
//TODO implement actionListForAccount
// In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 200, 403
}

public function actionViewForAccount($accountId, $contactId)
{
//TODO implement actionViewForAccount
// In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 200, 403
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public function checkAccess($action, $model = null, $params = [])
public function actionView($id)
{
//TODO implement actionView
// In order to conform with OpenAPI spec, response of this action must have one of the following HTTP status code: 200, 404
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

return [
'openApiPath' => '@specs/issue_fix/78_properties_that_are_marked_as_readonly_are_not_read_only/index.yaml',
'generateUrls' => false,
'generateModels' => true,
'excludeModels' => [
'Error',
],
'generateControllers' => false,
'generateMigrations' => false,
'generateModelFaker' => true, // `generateModels` must be `true` in order to use `generateModelFaker` as `true`
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
openapi: 3.0.3

info:
title: '#78'
version: 1.0.0

paths:
/:
get:
responses:
'200':
description: The Response

components:
schemas:
Payment:
properties:
id:
type: integer
amount:
type: integer
readOnly: true
currency:
type: string
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));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace app\models;

class Payment extends \app\models\base\Payment
{


}

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
namespace app\models;

use Faker\UniqueGenerator;

/**
* Fake data generator for Payment
* @method static Payment makeOne($attributes = [], ?UniqueGenerator $uniqueFaker = null);
* @method static Payment saveOne($attributes = [], ?UniqueGenerator $uniqueFaker = null);
* @method static Payment[] make(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null)
* @method static Payment[] save(int $number, $commonAttributes = [], ?UniqueGenerator $uniqueFaker = null)
*/
class PaymentFaker extends BaseModelFaker
{

/**
* @param array|callable $attributes
* @return Payment|\yii\db\ActiveRecord
* @example
* $model = (new PostFaker())->generateModels(['author_id' => 1]);
* $model = (new PostFaker())->generateModels(function($model, $faker, $uniqueFaker) {
* $model->scenario = 'create';
* $model->author_id = 1;
* return $model;
* });
**/
public function generateModel($attributes = [])
{
$faker = $this->faker;
$uniqueFaker = $this->uniqueFaker;
$model = new Payment();
//$model->id = $uniqueFaker->numberBetween(0, 1000000);
$model->amount = $faker->numberBetween(0, 1000000);
$model->currency = $faker->currencyCode;
if (!is_callable($attributes)) {
$model->setAttributes($attributes, false);
} else {
$model = $attributes($model, $faker, $uniqueFaker);
}
return $model;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/**
* This file is generated by Gii, do not change manually!
*/

namespace app\models\base;

/**
* This is the model class for table "payments".
*
* @property int $id
* @property int $amount
* @property string $currency
*
*/
abstract class Payment extends \yii\db\ActiveRecord
{
public static function tableName()
{
return '{{%payments}}';
}

public function rules()
{
return [
'trim' => [['currency'], 'trim'],
'currency_string' => [['currency'], 'string'],
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

return [
'openApiPath' => '@specs/issue_fix/79_response_status_codes_are_not_the_codes_defined_in_spec/index.yml',
'generateUrls' => false,
'generateModels' => false,
'excludeModels' => [
'Error',
],
'generateControllers' => true,
'generateMigrations' => false,
'generateModelFaker' => false,
];
Loading