Skip to content

Commit e3e62a8

Browse files
committed
fix #59
1 parent 03c33a2 commit e3e62a8

40 files changed

+324
-195
lines changed

src/generator/ApiGenerator.php

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use cebe\yii2openapi\lib\FractalGenerator;
1313
use cebe\yii2openapi\lib\items\DbModel;
1414
use cebe\yii2openapi\lib\items\FractalAction;
15+
use cebe\yii2openapi\lib\items\RestAction;
1516
use cebe\yii2openapi\lib\MigrationsGenerator;
1617
use cebe\yii2openapi\lib\PathAutoCompletion;
1718
use cebe\yii2openapi\lib\SchemaToDatabase;
@@ -20,6 +21,8 @@
2021
use Laminas\Code\Generator\ClassGenerator;
2122
use Laminas\Code\Generator\FileGenerator;
2223
use Laminas\Code\Generator\MethodGenerator;
24+
use Laminas\Code\Generator\ParameterGenerator;
25+
use Laminas\Code\Generator\ValueGenerator;
2326
use Yii;
2427
use yii\di\Instance;
2528
use yii\gii\CodeFile;
@@ -31,7 +34,6 @@
3134
use function array_filter;
3235
use function array_map;
3336
use function array_merge;
34-
use function array_unique;
3537
use const YII_ENV_TEST;
3638

3739
class ApiGenerator extends Generator
@@ -64,7 +66,7 @@ class ApiGenerator extends Generator
6466

6567
/**
6668
* @var bool use actions that return responses by JsonApi spec instead of default yii rest
67-
*/
69+
*/
6870
public $useJsonApi = false;
6971

7072
/**
@@ -122,7 +124,7 @@ class ApiGenerator extends Generator
122124
* 'User' => 'Profile', //use ProfileController for User model
123125
* 'File' => 'Upload', //use UploadController for File model
124126
* ]
125-
**/
127+
**/
126128
public $controllerModelMap = [];
127129

128130
/**
@@ -166,12 +168,12 @@ class ApiGenerator extends Generator
166168

167169
/**
168170
* @var DbModel[]
169-
**/
171+
**/
170172
private $preparedModels;
171173

172174
/**
173175
* @var \cebe\yii2openapi\lib\items\RestAction[]|\cebe\yii2openapi\lib\items\FractalAction
174-
**/
176+
**/
175177
private $preparedActions;
176178

177179
/**
@@ -266,7 +268,7 @@ public function rules()
266268
['transformerNamespace'],
267269
'required',
268270
'when' => function (ApiGenerator $model) {
269-
return (bool)$model->generateControllers && (bool) $model->useJsonApi;
271+
return (bool)$model->generateControllers && (bool)$model->useJsonApi;
270272
},
271273
],
272274
]
@@ -279,7 +281,7 @@ public function rules()
279281
* @throws \cebe\openapi\exceptions\TypeErrorException
280282
* @throws \cebe\openapi\exceptions\UnresolvableReferenceException
281283
*/
282-
public function validateSpec($attribute):void
284+
public function validateSpec($attribute): void
283285
{
284286
if ($this->ignoreSpecErrors) {
285287
return;
@@ -302,7 +304,7 @@ public function attributeLabels()
302304
'openApiPath' => 'OpenAPI 3 Spec file',
303305
'generateUrls' => 'Generate URL Rules',
304306
'generateModelsOnlyXTable' => 'Generate DB Models and Tables only for schemas that include `x-table` property',
305-
'skipUnderscoredSchemas'=>'Generate DB Models and Tables only for schemas that not starts with underscore'
307+
'skipUnderscoredSchemas' => 'Generate DB Models and Tables only for schemas that not starts with underscore'
306308
]
307309
);
308310
}
@@ -398,7 +400,7 @@ public function stickyAttributes()
398400
* @return CodeFile[] a list of code files to be created.
399401
* @throws \Exception
400402
*/
401-
public function generate():array
403+
public function generate(): array
402404
{
403405
return array_merge(
404406
$this->generateUrls(),
@@ -436,13 +438,13 @@ protected function generateUrls(): array
436438
protected function generateControllers(): array
437439
{
438440
$files = [];
439-
if (! $this->generateControllers) {
441+
if (!$this->generateControllers) {
440442
return $files;
441443
}
442444
$controllers = $this->prepareControllers();
443445
$controllerNamespace = $this->controllerNamespace ?? Yii::$app->controllerNamespace;
444446
$controllerPath = $this->getPathFromNamespace($controllerNamespace);
445-
$templateName = $this->useJsonApi? 'controller_jsonapi.php': 'controller.php';
447+
$templateName = $this->useJsonApi ? 'controller_jsonapi.php' : 'controller.php';
446448

447449
foreach ($controllers as $controller => $actions) {
448450
$className = Inflector::id2camel($controller) . 'Controller';
@@ -459,22 +461,7 @@ protected function generateControllers(): array
459461
);
460462
// only generate custom classes if they do not exist, do not override
461463
if (!file_exists(Yii::getAlias("$controllerPath/$className.php"))) {
462-
$classFileGenerator = new FileGenerator();
463-
$reflection = new ClassGenerator(
464-
$className,
465-
$controllerNamespace,
466-
null,
467-
$controllerNamespace . '\\base\\' . $className
468-
);
469-
470-
if ($this->useJsonApi) {
471-
$body = <<<'PHP'
472-
$actions = parent::actions();
473-
return $actions;
474-
PHP;
475-
$reflection->addMethod('actions', [], MethodGenerator::FLAG_PUBLIC, $body);
476-
}
477-
$classFileGenerator->setClasses([$reflection]);
464+
$classFileGenerator = $this->makeCustomController($className, $controllerNamespace, $actions);
478465
$files[] = new CodeFile(
479466
Yii::getAlias("$controllerPath/$className.php"),
480467
$classFileGenerator->generate()
@@ -660,7 +647,7 @@ protected function generateMigrations(): array
660647
* @throws \cebe\openapi\exceptions\TypeErrorException
661648
* @throws \cebe\openapi\exceptions\UnresolvableReferenceException
662649
*/
663-
protected function getOpenApi():OpenApi
650+
protected function getOpenApi(): OpenApi
664651
{
665652
if ($this->_openApi === null) {
666653
$file = Yii::getAlias($this->openApiPath);
@@ -679,7 +666,7 @@ protected function getOpenApi():OpenApi
679666
* @throws \cebe\openapi\exceptions\TypeErrorException
680667
* @throws \cebe\openapi\exceptions\UnresolvableReferenceException
681668
*/
682-
protected function getOpenApiWithoutReferences():OpenApi
669+
protected function getOpenApiWithoutReferences(): OpenApi
683670
{
684671
if ($this->_openApiWithoutRef === null) {
685672
$file = Yii::getAlias($this->openApiPath);
@@ -697,7 +684,7 @@ protected function getOpenApiWithoutReferences():OpenApi
697684
* @throws \yii\base\InvalidConfigException
698685
* @throws \Exception
699686
*/
700-
protected function prepareActions():array
687+
protected function prepareActions(): array
701688
{
702689
if (!$this->preparedActions) {
703690
$generator = $this->useJsonApi
@@ -718,7 +705,7 @@ protected function prepareActions():array
718705
* @return array|\cebe\yii2openapi\lib\items\RestAction[]|\cebe\yii2openapi\lib\items\FractalAction[]
719706
* @throws \Exception
720707
*/
721-
protected function prepareControllers():array
708+
protected function prepareControllers(): array
722709
{
723710
$actions = $this->prepareActions();
724711

@@ -732,7 +719,7 @@ protected function prepareControllers():array
732719
* @throws \cebe\openapi\exceptions\UnresolvableReferenceException
733720
* @throws \yii\base\InvalidConfigException
734721
*/
735-
protected function prepareModels():array
722+
protected function prepareModels(): array
736723
{
737724
if (!$this->preparedModels) {
738725
$converter = Yii::createObject([
@@ -756,7 +743,7 @@ protected function prepareTransformers(): array
756743
});
757744
$generator = new TransformerGenerator(
758745
$models,
759-
$this->transformerNamespace.($this->extendableTransformers? '\\base': ''),
746+
$this->transformerNamespace . ($this->extendableTransformers ? '\\base' : ''),
760747
$this->modelNamespace,
761748
$this->singularResourceKeys
762749
);
@@ -771,4 +758,51 @@ private function getPathFromNamespace(string $namespace)
771758
{
772759
return Yii::getAlias('@' . str_replace('\\', '/', $namespace));
773760
}
761+
762+
/**
763+
* @param string $className
764+
* @param string $controllerNamespace
765+
* @param RestAction[]|FractalAction[] $actions
766+
* @return FileGenerator
767+
*/
768+
protected function makeCustomController(string $className, string $controllerNamespace, array $actions): FileGenerator
769+
{
770+
$classFileGenerator = new FileGenerator();
771+
$reflection = new ClassGenerator(
772+
$className,
773+
$controllerNamespace,
774+
null,
775+
$controllerNamespace . '\\base\\' . $className
776+
);
777+
/**@var FractalAction[]|RestAction[] $abstractActions * */
778+
$abstractActions = array_filter($actions, function ($action) {
779+
return $action->shouldBeAbstract();
780+
});
781+
if ($this->useJsonApi) {
782+
$body = <<<'PHP'
783+
$actions = parent::actions();
784+
return $actions;
785+
PHP;
786+
$reflection->addMethod('actions', [], MethodGenerator::FLAG_PUBLIC, $body);
787+
}
788+
$params = [
789+
new ParameterGenerator('action'),
790+
new ParameterGenerator('model', null, new ValueGenerator(null)),
791+
new ParameterGenerator('params', null, new ValueGenerator([]))
792+
];
793+
$reflection->addMethod('checkAccess', $params, MethodGenerator::FLAG_PUBLIC, '//TODO implement checkAccess');
794+
foreach ($abstractActions as $action) {
795+
$params = array_map(function ($param) {
796+
return ['name' => $param];
797+
}, $action->getParamNames());
798+
$reflection->addMethod(
799+
$action->actionMethodName,
800+
$params,
801+
MethodGenerator::FLAG_PUBLIC,
802+
'//TODO implement ' . $action->actionMethodName
803+
);
804+
}
805+
$classFileGenerator->setClasses([$reflection]);
806+
return $classFileGenerator;
807+
}
774808
}

src/generator/default/controller.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,21 @@ public function afterAction($action, $result)
6262
* @param array $params additional parameters
6363
* @throws \yii\web\ForbiddenHttpException if the user does not have access
6464
*/
65-
public function checkAccess($action, $model = null, $params = [])
66-
{
67-
// TODO implement checkAccess
68-
}
65+
abstract public function checkAccess($action, $model = null, $params = []);
66+
6967
<?php foreach ($actions as $action): ?>
7068
<?php if (!$action->shouldUseTemplate()):?>
71-
69+
<?php if (!$action->shouldBeAbstract()):?>
7270
public function <?= $action->actionMethodName ?>(<?= $action->parameterList ?>)
7371
{
74-
<?=$action->getImplementation()?>
72+
<?=$action->getImplementation()?>
7573

7674
}
75+
76+
<?php else:?>
77+
abstract public function <?= $action->actionMethodName ?>(<?= $action->parameterList ?>);
78+
79+
<?php endif;?>
7780
<?php endif;?>
7881
<?php endforeach;?>
7982
<?php foreach ($actions as $action): ?>

src/generator/default/controller_jsonapi.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,19 @@ public function actions()
4444
* @param array $params additional parameters
4545
* @throws \yii\web\ForbiddenHttpException if the user does not have access
4646
*/
47-
public function checkAccess($action, $model = null, $params = [])
48-
{
49-
// TODO implement checkAccess
50-
}
47+
abstract public function checkAccess($action, $model = null, $params = []);
48+
5149
<?php foreach ($actions as $action): ?>
5250
<?php if (!$action->shouldUseTemplate()):?>
53-
51+
<?php if (!$action->shouldBeAbstract()):?>
5452
public function <?= $action->actionMethodName ?>(<?= $action->parameterList ?>)
5553
{
5654
<?=$action->getImplementation()?>
5755
}
56+
<?php else:?>
57+
abstract public function <?= $action->actionMethodName ?>(<?= $action->parameterList ?>);
58+
59+
<?php endif;?>
5860
<?php endif;?>
5961
<?php endforeach;?>
6062
<?php foreach ($actions as $action): ?>

src/lib/items/ActionTemplates.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class ActionTemplates
1818
'view' => [
1919
'class' => '\yii\rest\ViewAction::class',
2020
'implementation' => <<<'PHP'
21-
$model = $this->findModel($id);
21+
$model = $this->findModel($id);
2222
$this->checkAccess(ACTION_ID, $model);
2323
return $model;
2424
PHP
@@ -30,7 +30,7 @@ class ActionTemplates
3030
'update' => [
3131
'class' => '\yii\rest\UpdateAction::class',
3232
'implementation' => <<<'PHP'
33-
$model = $this->findModel($id);
33+
$model = $this->findModel($id);
3434
$this->checkAccess(ACTION_ID, $model);
3535
3636
$model->load(Yii::$app->getRequest()->getBodyParams(), '');
@@ -45,7 +45,7 @@ class ActionTemplates
4545
'delete' => [
4646
'class' => '\yii\rest\DeleteAction::class',
4747
'implementation' => <<<'PHP'
48-
$model = $this->findModel($id);
48+
$model = $this->findModel($id);
4949
$this->checkAccess(ACTION_ID, $model);
5050
5151
if ($model->delete() === false) {

src/lib/items/FractalAction.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,20 +189,22 @@ public function getTemplate():?string
189189
return $this->templateFactory()->getTemplate();
190190
}
191191

192-
193-
public function getImplementation():?string
192+
public function shouldBeAbstract(): bool
194193
{
195194
$maybeImplemented = [RouteData::TYPE_PROFILE, RouteData::TYPE_DEFAULT, RouteData::TYPE_RESOURCE_OPERATION];
196195
if ((!$this->modelName || !$this->hasTemplate()) && !in_array($this->type, $maybeImplemented, true)) {
197-
return " // TODO implement {$this->actionMethodName}\n";
196+
return true;
198197
}
199198
if ($this->hasStandardId() && !in_array($this->type, $maybeImplemented, true)) {
200-
return null; //Default template action used
199+
return false; //Default template action used
201200
}
202-
203201
if (!$this->templateFactory()->hasImplementation()) {
204-
return " // TODO implement {$this->actionMethodName}\n";
202+
return true;
205203
}
204+
return false;
205+
}
206+
public function getImplementation():?string
207+
{
206208
return $this->templateFactory()->getImplementation();
207209
}
208210

src/lib/items/RestAction.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,18 +161,25 @@ public function getSerializerConfig():?string
161161
return null;
162162
}
163163

164-
public function getImplementation():?string
164+
public function shouldBeAbstract(): bool
165165
{
166166
if (!$this->modelName || !$this->hasTemplate()) {
167-
return " // TODO implement {$this->actionMethodName}";
167+
return true;
168168
}
169+
169170
if ($this->hasStandardId()) {
170-
return null; //Default template action used
171+
return false; //Default template action used
171172
}
172173

173174
if (!ActionTemplates::hasImplementation($this->id)) {
174-
return " // TODO implement {$this->actionMethodName}";
175+
return true;
175176
}
177+
178+
return false;
179+
}
180+
181+
public function getImplementation():?string
182+
{
176183
$template = ActionTemplates::getTemplate($this->id);
177184
return strtr(
178185
$template['implementation'],

0 commit comments

Comments
 (0)