Class luya\admin\openapi\UrlRuleRouteParser

Inheritanceluya\admin\openapi\UrlRuleRouteParser » luya\admin\openapi\BasePathParser
Available since version3.2.0
Source Code https://github.com/luyadev/luya-module-admin/blob/master/src/openapi/UrlRuleRouteParser.php

Generate a Path for a $rules array containg UrlRule objects.

Public Methods

Hide inherited methods

Method Description Defined By
__construct() Generate new UrlRule Route Parser luya\admin\openapi\UrlRuleRouteParser
generateOperationId() Generate a readable operation id for current route and verb. luya\admin\openapi\BasePathParser
getActionNameFromRoute() luya\admin\openapi\UrlRuleRouteParser
getOperations() Return all operations luya\admin\openapi\UrlRuleRouteParser
getPath() Returns the path which should be associated with this endpoint. luya\admin\openapi\UrlRuleRouteParser
getPathItem() Return a PathItem. luya\admin\openapi\UrlRuleRouteParser
isValid() Whether this Parser is valid or not. luya\admin\openapi\UrlRuleRouteParser
normalizeTag() Generate a normalized tag from a given route. luya\admin\openapi\BasePathParser
routes() Returns all absolute controller map routes which are covered by this parser. luya\admin\openapi\UrlRuleRouteParser

Protected Methods

Hide inherited methods

Method Description Defined By
getOperation() Get the Operation luya\admin\openapi\UrlRuleRouteParser

Property Details

Hide inherited properties

$controller protected property

The created controller object from {{$controllerMapRoute}}.

$controllerMapRoute protected property
protected string $controllerMapRoute null
$controllerSpecs protected property
$endpointName protected property

The endpoint name to categorzied operations together under the same tag.

protected string $endpointName null
$patternRoute protected property
protected string $patternRoute null
$rules protected property

An array with {{yii\web\UrlRule}} objects

protected array $rules null

Method Details

Hide inherited methods

__construct() public method

Generate new UrlRule Route Parser

public void __construct ( $patternRoute, $controllerMapRoute, array $rules, $endpointName )
$patternRoute string

The pattern which will be taken to generate the path for all routes, f.e. my-users.

$controllerMapRoute string

The controller map which will be taken to generate a new controller, f.e. user/index.

$rules array

An array with {{yii\web\UrlRule}} objects f.e [new UrlRule(['pattern' => 'my-users', 'route' => 'user/index', 'verb' => 'GET'])]

$endpointName string

The endpoint name is used to categorize all operations together into this tag f.e. v1/my-users.

                public function __construct($patternRoute, $controllerMapRoute, array $rules, $endpointName)
{
    $this->patternRoute = $patternRoute;
    $this->controllerMapRoute = $controllerMapRoute;
    $this->rules = $rules;
    $createController = Yii::$app->createController($controllerMapRoute);
    if ($createController) {
        $this->controller = $createController[0];
    }
    if ($this->controller) {
        $this->controllerSpecs = new ControllerSpecs($this->controller);
    }
    $this->endpointName = $endpointName;
}

            
generateOperationId() public method

Defined in: luya\admin\openapi\BasePathParser::generateOperationId()

Generate a readable operation id for current route and verb.

public string generateOperationId ( $verb )
$verb string

                public function generateOperationId($verb)
{
    $path = ltrim(str_replace(["admin/api-", "admin/api", "admin/"], '', $this->getPath()), '/');
    $operation = $verb . '-'. str_replace("/", " ", $path); // replace slashes with newlines
    $camelCase = Inflector::slug($operation, '-', true, false);
    return Generator::generateUniqueOperationId(Inflector::id2camel($camelCase));
}

            
getActionNameFromRoute() public method

public void getActionNameFromRoute ( $route )
$route

                public function getActionNameFromRoute($route)
{
    $parts = explode("/", $route);
    return end($parts);
}

            
getOperation() protected method

Get the Operation

protected \cebe\openapi\spec\Operation|boolean getOperation ( yii\web\UrlRule $urlRule, $verbName )
$urlRule yii\web\UrlRule
$verbName string
return \cebe\openapi\spec\Operation|boolean

Either the operation or false is returned.

                protected function getOperation(UrlRule $urlRule, $verbName)
{
    if (empty($urlRule->verb)) {
        return false;
    }
    Yii::debug("Get Operation '{$urlRule->route}' with pattern '{$urlRule->pattern}'", __METHOD__);
    $actionSpecs = new ControllerActionSpecs($this->controller, $this->getActionNameFromRoute($urlRule->route), $verbName);
    $actionObject = $actionSpecs->getActionObject();
    if (!$actionObject || ObjectHelper::isInstanceOf($actionObject, OptionsAction::class, false)) {
        return false;
    }
    $params = [];
    $registeredParams = [];
    preg_match_all('/{+(.*?)}/', $this->getPath(), $matches);
    if (isset($matches[1])) {
        foreach ($matches[1] as $param) {
            $registeredParams[] = $param;
            $params[] = new Parameter([
                'name' => $param,
                'in' => 'path',
                'required' => true,
                'schema' => new Schema(['type' => 'string'])
            ]);
        }
    }
    foreach ($actionSpecs->getParameters() as $param) {
        if ($param instanceof Parameter && !in_array($param->name, $registeredParams)) {
            $params[] = $param;
        }
    }
    $requestBody = false;
    if ($actionObject instanceof UpdateAction || $actionObject instanceof CreateAction) {
        $schema = $actionSpecs->createActiveRecordSchemaFromObject($actionObject, false);
        if (!$schema) {
            return false;
        }
        $requestBody = new RequestBody([
            'required' => true,
            'content' => [
                'application/json' => new MediaType([
                    'schema' => $schema,
                ])
            ]
        ]);
    } elseif (strtoupper($verbName) == 'POST') {
        // if its a post request endpoint and @uses is defined use this
        // information as request body.
        $useProperties = [];
        /** @var PhpDocUses $use */
        foreach ($actionSpecs->getPhpDocParser()->getUses() as $use) {
            if ($use->getType()->getIsClass()) {
                $schema = $actionSpecs->createActiveRecordSchemaObjectFromClassName($use->getType()->getClassName());
                if ($schema) {
                    $requestBody = new RequestBody([
                        'content' => [
                            'application/json' => new MediaType([
                                'schema' => [
                                    'type' => 'object',
                                    'properties' => $schema->getProperties()
                                ]
                            ])
                        ]
                    ]);
                }
            } else {
                $useProperties[$use->getDescription()] = new Schema([
                    'type' => $use->getType()->getNoramlizeName(),
                    'title' => $use->getDescription(),
                ]);
            }
        }
        if (!empty($useProperties)) {
            $requestBody = new RequestBody([
                'content' => [
                    'application/json' => new MediaType([
                        'schema' => [
                            'type' => 'object',
                            'properties' => $useProperties,
                        ]
                    ])
                ]
            ]);
        }
    }
    // check if an @method phpdoc is available for the current controller:
    $phpDocMethod = $this->controllerSpecs->getPhpDocParser()->getMethod($actionSpecs->getActionName());
    if ($phpDocMethod) {
        $summary = $phpDocMethod->getNormalizedMethodName();
        $description = $phpDocMethod->getDescription();
    } else {
        $summary = $actionSpecs->getSummary();
        $description = $actionSpecs->getDescription();
    }
    return new Operation(array_filter([
        'tags' => [$this->normalizeTag($this->endpointName)],
        'summary' => $summary,
        'description' => $description,
        'operationId' => $this->generateOperationId($verbName),
        'parameters' => $params,
        'responses' => new Responses($actionSpecs->getResponses()),
        'requestBody' => $requestBody,
    ]));
}

            
getOperations() public method

Return all operations

public array getOperations ( )

                public function getOperations()
{
    if ($this->_operations !== null) {
        return $this->_operations;
    }
    $operations = [];
    /** @var UrlRule $urlRule */
    foreach ($this->rules as $urlRule) {
        $verbName = current($urlRule->verb);
        $operation = $this->getOperation($urlRule, $verbName);
        if ($operation) {
            $operations[$verbName] = $operation;
            $this->_coveredRoutes[] = $urlRule->route;
        }
    }
    $this->_operations = $operations;
    return $operations;
}

            
getPath() public method

Returns the path which should be associated with this endpoint.

This is the actual route which then recieves the request.

public string getPath ( )

                public function getPath(): string
{
    $route = $this->patternRoute;
    preg_match_all('/\<(\w+)(.*?)\>/', $route, $matches);
    if (isset($matches[2])) {
        foreach ($matches[2] as $regex) {
            $route = str_replace($regex, '', $route);
        }
    }
    return '/'.ltrim(str_replace(['<','>'], ['{', '}'], $route), '/');
}

            
getPathItem() public method

Return a PathItem.

A PathItem represents a path within the openapi definition. A path (or maybe also named as endpoint/route) can have multiple verbs. Like post, get, put

public \cebe\openapi\spec\PathItem getPathItem ( )

                public function getPathItem(): PathItem
{
    $config = [
        'summary' => $this->controllerSpecs->getSummary(),
        'description' => $this->controllerSpecs->getDescription(),
    ];
    foreach ($this->getOperations() as $verb => $operation) {
        $config[strtolower($verb)] = $operation;
    }
    return new PathItem($config);
}

            
isValid() public method

Whether this Parser is valid or not.

public boolean isValid ( )

                public function isValid(): bool
{
    return $this->controller && !empty($this->getOperations()) ? true : false;
}

            
normalizeTag() public method

Defined in: luya\admin\openapi\BasePathParser::normalizeTag()

Generate a normalized tag from a given route.

public string normalizeTag ( $route )
$route string

                public function normalizeTag($route)
{
    $route = str_replace(["admin/"], '', $route);
    return ltrim(trim($route, '/'));
}

            
routes() public method

Returns all absolute controller map routes which are covered by this parser.

For example the update and post route are difference and covered, it would be:

  • admin/api-admin-user/create
  • admin/api-admin-user/update
public array routes ( )

                public function routes(): array
{
    return $this->_coveredRoutes;
}