Abstract Class luya\admin\openapi\specs\BaseSpecs

Inheritanceluya\admin\openapi\specs\BaseSpecs
Implementsluya\admin\openapi\specs\SpecInterface
Subclassesluya\admin\openapi\specs\ControllerActionSpecs, luya\admin\openapi\specs\ControllerSpecs
Available since version3.2.0
Source Code https://github.com/luyadev/luya-module-admin/blob/master/src/openapi/specs/BaseSpecs.php

Generate Specs Details.

  • works with the class php doc block
  • works with the method php doc block

Public Properties

Hide inherited properties

Property Type Description Defined By
$contexts luya\admin\openapi\specs\BaseSpecs

Protected Methods

Hide inherited methods

Method Description Defined By
extractModelClassFromObject() Extract the modelClass property value from any object luya\admin\openapi\specs\BaseSpecs
generateResponseArrayFromModel() Generate an Array Response from ActiveRecord/Model class. luya\admin\openapi\specs\BaseSpecs
getResponseContent() Generate the response content luya\admin\openapi\specs\BaseSpecs
getValidationResponseContent() Get validation response for post requests luya\admin\openapi\specs\BaseSpecs

Property Details

Hide inherited properties

$contexts public static property
public static $contexts = []

Method Details

Hide inherited methods

createActiveRecordSchemaFromObject() public method

Create an ActiveRecord Schema Array Response from an Object (Controller or Action Object).

public array|false createActiveRecordSchemaFromObject ( $actionObject, $asArray false )
$actionObject object

An Action or Controller object.

$asArray boolean

                public function createActiveRecordSchemaFromObject($actionObject, $asArray = false)
{
    $class = $this->extractModelClassFromObject($actionObject);
    if ($class) {
        $object = $this->createActiveRecordSchemaObjectFromClassName($class);
        if ($object) {
            return $this->createSchemaFromActiveRecordToSchemaObject($object, $asArray);
        }
    }
    return false;
}

            
createActiveRecordSchemaObjectFromClassName() public method

Create the ActiveRecordToSchema object from an ActiveRecord/Model Class Name.

public luya\admin\openapi\specs\ActiveRecordToSchema|boolean createActiveRecordSchemaObjectFromClassName ( $activeRecordClassName, $senderActiveRecordClassName null )
$activeRecordClassName string|array
$senderActiveRecordClassName string

The class name which has created the new active record, this is used to find circular reference which end in infinite loops.

                public function createActiveRecordSchemaObjectFromClassName($activeRecordClassName, $senderActiveRecordClassName = null)
{
    try {
        Yii::warning("Create object createActiveRecordSchemaObjectFromClassName {$activeRecordClassName}", __METHOD__);
        $object = $this->createObjectFromClassName($activeRecordClassName);
        if ($object instanceof Model) {
            return new ActiveRecordToSchema($this, $object, $senderActiveRecordClassName);
        }
    } catch (\Exception $e) {
    }
    return false;
}

            
createObjectFromClassName() public method

Create the Object from a ClassName

public object|boolean createObjectFromClassName ( $className )
$className string

                public function createObjectFromClassName($className)
{
    try {
        Yii::info("Create object createObjectFromClassName {$className}", __METHOD__);
        if (!Yii::$container->hasSingleton($className)) {
            Yii::$container->setSingleton($className);
        }
        return Yii::createObject($className);
    } catch (\Exception $e) {
        Yii::warning("Error while creating the model class {$className}", __METHOD__);
    }
    return false;
}

            
createSchemaFromActiveRecordToSchemaObject() public method

Generate OpenAPI schema structure from ActiveRecordToSchema Object

public array createSchemaFromActiveRecordToSchemaObject ( luya\admin\openapi\specs\ActiveRecordToSchema $activeRecord, $isArray false )
$activeRecord luya\admin\openapi\specs\ActiveRecordToSchema
$isArray boolean

                public function createSchemaFromActiveRecordToSchemaObject(ActiveRecordToSchema $activeRecord, $isArray = false)
{
    if ($isArray) {
        return [
            'type' => 'array',
            'items' => [
                'type' => 'object',
                'properties' => $activeRecord->getProperties()
            ]
        ];
    }
    return [
        'type' => 'object',
        'properties' => $activeRecord->getProperties()
    ];
}

            
extractModelClassFromObject() protected method

Extract the modelClass property value from any object

protected string|boolean extractModelClassFromObject ( $actionObject )
$actionObject object

                protected function extractModelClassFromObject($actionObject)
{
    if (is_object($actionObject) && ObjectHelper::isInstanceOf($actionObject, [Api::class, Action::class], false)) {
        return $this->getActionObject()->modelClass;
    }
    return false;
}

            
generateResponseArrayFromModel() protected method

Generate an Array Response from ActiveRecord/Model class.

protected array|boolean generateResponseArrayFromModel ( $modelClassName, $isArray false )
$modelClassName
$isArray boolean

                protected function generateResponseArrayFromModel($modelClassName, $isArray = false)
{
    $key = implode("", [$modelClassName, (int) $isArray]);
    if (array_key_exists($key, self::$contexts)) {
        return self::$contexts[$key];
    }
    $response = $this->internalGenerateResponseArrayFromModel($modelClassName, $isArray);
    self::$contexts[$key] = $response;
    return $response;
}

            
getActionObject() public abstract method

public abstract yii\base\Action getActionObject ( )

                abstract public function getActionObject();

            
getControllerObject() public abstract method

public abstract yii\base\Controller getControllerObject ( )

                abstract public function getControllerObject();

            
getDescription() public method

public void getDescription ( )

                public function getDescription(): string
{
    return $this->getPhpDocParser()->getLongDescription();
}

            
getParameters() public method

public void getParameters ( )

                public function getParameters(): array
{
    $params = [];
    if ($this->getReflection() instanceof ReflectionMethod) {
        foreach ($this->getReflection()->getParameters() as $arg) {
            $paramDoc = $this->getPhpDocParser()->getParam($arg->getName());
            $paramType = $paramDoc->getType()->getNoramlizeName();
            $params[] = new Parameter([
                'name' => $arg->getName(),
                'in' => 'query',
                'required' => !$arg->isOptional(),
                'description' => $paramDoc->getDescription(),
                'schema' => new Schema([
                    'type' => in_array($paramType, ['integer', 'string']) ? $paramType : 'string', // only integer and string allowed
                ])
            ]);
        }
    }
    if (ObjectHelper::isInstanceOf($this->getActionObject(), [IndexAction::class], false)) {
        // fields
        $params['fields'] = new Parameter([
            'name' => 'fields',
            'in' => 'query',
            'required' => false,
            'description' => 'Provide a comma seperated list of fields which should be returned.',
            'example' => 'id,email,firstname,lastname',
            'schema' => new Schema(['type' => 'string']),
        ]);
        $activeRecordClassName = $this->extractModelClassFromObject($this->getActionObject());
        $activeRecord = $this->createObjectFromClassName($activeRecordClassName);
        if ($activeRecord && method_exists($activeRecord, 'extraFields')) {
            $expandExample = implode(",", $activeRecord->extraFields());
        } else {
            $expandExample = null;
        }
        // expand
        $params['expand'] = new Parameter([
            'name' => 'expand',
            'in' => 'query',
            'required' => false,
            'description' => 'A comma seperated list of extra attributes (for example relations) which should be expanded.',
            'example' => $expandExample,
            'schema' => new Schema(['type' => 'string']),
        ]);
        // page
        $params['page'] = new Parameter([
            'name' => 'page',
            'in' => 'query',
            'required' => false,
            'description' => 'The page which should be resolved, page always starts at 1.',
            'example' => '1',
            'schema' => new Schema(['type' => 'integer']),
        ]);
        // per-page
        $params['per-page'] = new Parameter([
            'name' => 'per-page',
            'in' => 'query',
            'required' => false,
            'description' => 'The amount of rows to return by a page. By default its 25 rows and usually can not exceed 100 rows.',
            'example' => '100',
            'schema' => new Schema(['type' => 'integer']),
        ]);
    }
    if (property_exists($this->getControllerObject(), 'filterSearchModelClass')) {
        $dataFilterModelClass = $this->getControllerObject()->filterSearchModelClass;
        if (!empty($dataFilterModelClass)) {
            // filter
            $params['filter'] = new Parameter([
                'name' => 'filter',
                'in' => 'query',
                'required' => false,
                'description' => 'It allows validating and building a filter condition passed via request. See https://luya.io/guide/ngrest-api#filtering',
                'example' => 'filter[from][gt]=123456&filter[to][lt]=123456',
                /* Multiple example are not yet rendered by redoc: */
                /* https://github.com/Redocly/redoc/issues/858 */
                /*
                'examples' => [
                ],
                */
                'schema' => $this->createSchemaFromActiveRecordToSchemaObject($this->createActiveRecordSchemaObjectFromClassName($dataFilterModelClass), false)
            ]);
        }
    }
    // _language
    $params['_lang'] = new Parameter([
        'name' => '_lang',
        'in' => 'query',
        'required' => false,
        'description' => 'Defines the application language to format locale specific content or return the language specific content for multi language fields.',
        'example' => '`en`, `fr_FR` or `de-ch`',
        'schema' => new Schema(['type' => 'string']),
    ]);
    $event = new PathParametersEvent([
        'params' => $params,
        'controllerClass' => get_class($this->getControllerObject()),
        'actionClass' => get_class($this->getActionObject()),
        'verbName' => $this->getVerbName(),
        'contextClass' => $this->getReflection()->getName(),
        'sender' => $this,
    ]);
    Event::trigger(Generator::class, Generator::EVENT_PATH_PARAMETERS, $event);
    return $event->params;
}

            
getPhpDocParser() public method

public luya\admin\openapi\phpdoc\PhpDocParser getPhpDocParser ( )

                public function getPhpDocParser()
{
    if ($this->_phpDocParser === null) {
        $this->_phpDocParser = new PhpDocParser($this->getReflection());
    }
    return $this->_phpDocParser;
}

            
getReflection() public abstract method

public abstract ReflectionClass|ReflectionMethod getReflection ( )

                abstract public function getReflection();

            
getResponseContent() protected method

Generate the response content

protected array getResponseContent ( )

                protected function getResponseContent()
{
    $modelClass = $this->extractModelClassFromObject($this->getActionObject());
    if ($modelClass) {
        // the index action should return an array of objects
        $isArray = ObjectHelper::isInstanceOf($this->getActionObject(), [IndexAction::class], false);
        return $this->generateResponseArrayFromModel($modelClass, $isArray);
    }
    /** @var PhpDocType $type */
    $type = $this->getPhpDocParser()->getReturn()->getType();
    if (!$type) {
        return [];
    }
    // handle php object type
    if ($type->getIsClass()) {
        return $this->generateResponseArrayFromModel($type->getClassName(), $type->getIsArray());
    }
    // handle type array
    if ($type->getIsArray()) {
        return [
            'application/json' => new MediaType([
                'schema' => [
                    'type' => 'array',
                    'items' => [
                        'type' => 'string'
                    ],
                ],
            ])
        ];
    }
    if ($type->getIsScalar()) {
        return [
            'application/json' => new MediaType([
                'schema' => [
                    'type' => $type->getNoramlizeName(),
                ],
            ])
        ];
    }
    if ($type->getIsObject()) {
        return [
            'application/json' => new MediaType([
                'schema' => [
                    'type' => 'object',
                ],
            ])
        ];
    }
    return [];
}

            
getResponses() public method

public void getResponses ( )

                public function getResponses(): array
{
    $return = $this->getPhpDocParser()->getReturn();
    $response = new Response([]);
    $response->description = $return->getDescription();
    $responseContent = $this->getResponseContent();
    if (!empty($responseContent)) {
        $response->content = $responseContent;
        $statusCode = 200;
    } else {
        $statusCode = 204;
    }
    $responseCodes = [
        $statusCode => $response,
        401 => new Response(['description' => 'Authentication failed.']),
        404 => new Response(['description' => 'The requested resource does not exist.']),
        405 => new Response(['description' => 'Method not allowed.']),
        500 => new Response(['description' => 'Internal server error.']),
    ];
    if ($this->getVerbName() == 'post' || $this->getVerbName() == 'put') {
        $responseCodes[422] = $this->getValidationResponseContent();
    }
    return $responseCodes;
}

            
getSummary() public method

public void getSummary ( )

                public function getSummary(): string
{
    return $this->getPhpDocParser()->getShortSummary();
}

            
getValidationResponseContent() protected method

Get validation response for post requests

protected \cebe\openapi\spec\Response getValidationResponseContent ( )

                protected function getValidationResponseContent()
{
    return new Response([
        'description' => 'Data validation failed. Check the response body for detailed error messages.',
        'content' => [
            'application/json' => new MediaType([
                'schema' => [
                    'type' => 'array',
                    'items' => [
                        'type' => 'object',
                        'properties' => [
                            'field' => [
                                'type' => 'string',
                                'example' => 'email',
                            ],
                            'message' => [
                                'type' => 'string',
                                'example' => 'Unable to find the given user, email or password is wrong.'
                            ]
                        ]
                    ]
                ],
            ])
        ]
    ]);
}

            
getVerbName() public abstract method

Get the context verbname:

  • get
  • post
  • delete
  • put
  • optionĀ§
public abstract string getVerbName ( )

                abstract public function getVerbName();