1212use cebe \yii2openapi \lib \FractalGenerator ;
1313use cebe \yii2openapi \lib \items \DbModel ;
1414use cebe \yii2openapi \lib \items \FractalAction ;
15+ use cebe \yii2openapi \lib \items \RestAction ;
1516use cebe \yii2openapi \lib \MigrationsGenerator ;
1617use cebe \yii2openapi \lib \PathAutoCompletion ;
1718use cebe \yii2openapi \lib \SchemaToDatabase ;
2021use Laminas \Code \Generator \ClassGenerator ;
2122use Laminas \Code \Generator \FileGenerator ;
2223use Laminas \Code \Generator \MethodGenerator ;
24+ use Laminas \Code \Generator \ParameterGenerator ;
25+ use Laminas \Code \Generator \ValueGenerator ;
2326use Yii ;
2427use yii \di \Instance ;
2528use yii \gii \CodeFile ;
3134use function array_filter ;
3235use function array_map ;
3336use function array_merge ;
34- use function array_unique ;
3537use const YII_ENV_TEST ;
3638
3739class 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}
0 commit comments