17 use Magento\Webapi\Model\Rest\SwaggerFactory;
94 'boolean' =>
'boolean',
96 'integer' =>
'integer',
100 'string' =>
'string',
101 TypeProcessor::ANY_TYPE =>
'string',
102 TypeProcessor::NORMALIZED_ANY_TYPE =>
'string',
139 protected function generateSchema($requestedServiceMetadata, $requestScheme, $requestHost, $endpointUrl)
142 $swagger = $this->swaggerFactory->create();
147 $swagger->setHost($requestHost);
148 $swagger->setBasePath(strstr($endpointUrl, Rest::SCHEMA_PATH,
true));
149 $swagger->setSchemes([$requestScheme]);
151 foreach ($requestedServiceMetadata as $serviceName => $serviceData) {
152 if (!isset($this->tags[$serviceName])) {
153 $this->tags[$serviceName] = $this->
generateTagInfo($serviceName, $serviceData);
154 $swagger->addTag($this->tags[$serviceName]);
157 $uri = $this->convertPathParams($uri);
158 foreach ($httpMethods as $httpOperation => $httpMethodData) {
159 $httpOperation = strtolower($httpOperation);
162 $httpMethodData[
'uri'] = $uri;
163 $httpMethodData[
'httpOperation'] = $httpOperation;
165 $this->convertPathParams($uri),
174 return $swagger->toSchema();
184 $versionParts = explode(
'.', $this->productMetadata->getVersion());
185 if (!isset($versionParts[0]) || !isset($versionParts[1])) {
188 $majorMinorVersion = $versionParts[0] .
'.' . $versionParts[1];
191 'version' => $majorMinorVersion,
192 'title' => $this->productMetadata->getName() .
' ' . $this->productMetadata->getEdition(),
209 $operationId .= ucfirst($methodName);
212 'tags' => [$tagName],
213 'description' => $methodData[
'documentation'],
214 'operationId' => $operationId,
217 $parameters = $this->generateMethodParameters($httpMethodData, $operationId);
219 $pathInfo[
'parameters'] = $parameters;
236 if (isset($methodData[
'interface'][
'out'][
'parameters'])
237 && is_array($methodData[
'interface'][
'out'][
'parameters'])
239 $parameters = $methodData[
'interface'][
'out'][
'parameters'];
240 $responses = $this->generateMethodSuccessResponse($parameters, $responses);
244 if (isset($methodData[
'resources'])) {
245 foreach ($methodData[
'resources'] as $resourceName) {
246 if ($resourceName !==
'anonymous') {
248 $responses[WebapiException::HTTP_UNAUTHORIZED][
'schema'][
'$ref'] =
self::ERROR_SCHEMA;
254 if (isset($methodData[
'interface'][
'out'][
'throws'])
255 && is_array($methodData[
'interface'][
'out'][
'throws'])
257 foreach ($methodData[
'interface'][
'out'][
'throws'] as $exceptionClass) {
258 $responses = $this->generateMethodExceptionErrorResponses($exceptionClass, $responses);
261 $responses[
'default'][
'description'] =
'Unexpected error';
276 private function generateMethodParameters($httpMethodData, $operationId)
283 if (!isset($phpMethodData[
'interface'][
'in'][
'parameters'])
284 || !isset($httpMethodData[
'uri'])
285 || !isset($httpMethodData[
'httpOperation'])
290 foreach ($phpMethodData[
'interface'][
'in'][
'parameters'] as $parameterName => $parameterInfo) {
292 if (isset($httpMethodData[
'parameters'][$parameterName][
'force'])
293 && $httpMethodData[
'parameters'][$parameterName][
'force']
298 if (!isset($parameterInfo[
'type'])) {
301 $description = isset($parameterInfo[
'documentation']) ? $parameterInfo[
'documentation'] :
null;
304 if (strpos($httpMethodData[
'uri'],
'{' . $parameterName .
'}') !==
false) {
305 $parameters[] = $this->generateMethodPathParameter($parameterName, $parameterInfo,
$description);
306 }
elseif (strtoupper($httpMethodData[
'httpOperation']) ===
'GET') {
307 $parameters = $this->generateMethodQueryParameters(
314 $bodySchema = $this->generateBodySchema(
326 preg_match_all(
'#\\{([^\\{\\}]*)\\}#', $httpMethodData[
'uri'], $allPathParams);
327 $remainingPathParams = array_diff(
329 array_keys($phpMethodData[
'interface'][
'in'][
'parameters'])
331 foreach ($remainingPathParams as $pathParam) {
333 'name' => $pathParam,
342 $bodyParam[
'name'] = $operationId .
'Body';
343 $bodyParam[
'in'] =
'body';
344 $bodyParam[
'schema'] = $bodySchema;
345 $parameters[] = $bodyParam;
384 $tagInfo[
'name'] = $serviceName;
385 if (!empty($serviceData) && is_array($serviceData)) {
401 if ($simpleType ==
false) {
406 $trimedTypeName = rtrim($typeName,
'[]');
408 $result[
'items'] = [
'type' => $simpleType];
410 if (strpos($typeName,
'[]') !==
false) {
417 $this->definitions[$definitionKey] = [];
422 $result = [
'type' => $simpleType];
439 $requiredProperties = [];
440 $typeData = $this->typeProcessor->getTypeData($typeName);
441 if (isset($typeData[
'parameters'])) {
442 foreach ($typeData[
'parameters'] as $parameterName => $parameterData) {
444 $parameterData[
'type'],
445 $parameterData[
'documentation']
447 if ($parameterData[
'required']) {
448 $requiredProperties[] = $parameterName;
452 $definition = [
'type' =>
'object'];
453 if (isset($typeData[
'documentation'])) {
454 $definition[
'description'] = $typeData[
'documentation'];
459 if (!empty($requiredProperties)) {
460 $definition[
'required'] = $requiredProperties;
475 'error-response' => [
480 'description' =>
'Error message',
483 '$ref' =>
'#/definitions/error-errors',
487 'description' =>
'Error code',
490 '$ref' =>
'#/definitions/error-parameters',
494 'description' =>
'Stack trace',
497 'required' => [
'message'],
501 'description' =>
'Errors list',
503 '$ref' =>
'#/definitions/error-errors-item',
506 'error-errors-item' => [
508 'description' =>
'Error details',
512 'description' =>
'Error message',
515 '$ref' =>
'#/definitions/error-parameters',
519 'error-parameters' => [
521 'description' =>
'Error parameters list',
523 '$ref' =>
'#/definitions/error-parameters-item',
526 'error-parameters-item' => [
528 'description' =>
'Error parameters item',
532 'description' =>
'ACL resource',
536 'description' =>
'Missing or invalid field name' 540 'description' =>
'Incorrect field value' 545 $this->snakeCaseDefinitions($this->definitions)
558 if (!empty($vals[
'properties'])) {
559 $definitions[
$name][
'properties'] = $this->convertArrayToSnakeCase($vals[
'properties']);
561 if (!empty($vals[
'required'])) {
562 $snakeCaseRequired = [];
563 foreach ($vals[
'required'] as $requiredProperty) {
564 $snakeCaseRequired[] = SimpleDataObjectConverter::camelCaseToSnakeCase($requiredProperty);
578 private function convertArrayToSnakeCase(
$properties)
581 $snakeCaseName = SimpleDataObjectConverter::camelCaseToSnakeCase(
$name);
612 return strtolower(preg_replace(
'/(.)([A-Z])/',
"$1-$2", $typeName));
633 foreach ($this->serviceTypeList->getDataTypes() as $customAttributeClass) {
634 $this->typeProcessor->register($customAttributeClass);
646 return $this->serviceMetadata->getRouteMetadata($serviceName);
657 if (array_key_exists(
$type, $this->simpleTypeList)) {
658 return $this->simpleTypeList[
$type];
678 if ($this->typeProcessor->isTypeSimple(
$type)) {
687 if ($this->typeProcessor->isArrayType(
$type)) {
689 $arrayType = substr(
$type, 0, -2);
690 return $this->handleComplex(
$name, $arrayType,
$prefix,
true);
708 $parameters = $this->typeProcessor->getTypeData(
$type)[
'parameters'];
710 foreach ($parameters as $subParameterName => $subParameterInfo) {
711 $subParameterType = $subParameterInfo[
'type'];
712 $subParameterDescription = isset($subParameterInfo[
'documentation'])
713 ? $subParameterInfo[
'documentation']
721 $queryNames = array_merge(
723 $this->
getQueryParamNames($subParameterName, $subParameterType, $subParameterDescription, $subPrefix)
749 private function convertPathParams($uri)
751 $parts = explode(
'/', $uri);
754 if (strpos($parts[
$i],
':') === 0) {
755 $parts[
$i] =
'{' . substr($parts[
$i], 1) .
'}';
758 return implode(
'/', $parts);
769 private function generateMethodPathParameter($parameterName, $parameterInfo,
$description)
772 'name' => $parameterName,
793 private function generateMethodQueryParameters($parameterName, $parameterInfo,
$description, $parameters)
796 if (count($queryParams) === 1) {
798 $parameters[] = $this->createQueryParam(
800 $parameterInfo[
'type'],
802 $parameterInfo[
'required']
810 foreach ($queryParams as
$name => $queryParamInfo) {
811 $parameters[] = $this->createQueryParam(
813 $queryParamInfo[
'type'],
814 $queryParamInfo[
'description']
830 private function generateBodySchema($parameterName, $parameterInfo,
$description, $bodySchema)
832 $required = isset($parameterInfo[
'required']) ? $parameterInfo[
'required'] :
null;
838 $bodySchema[
'required'][] = $parameterName;
841 $parameterInfo[
'type'],
844 $bodySchema[
'type'] =
'object';
855 private function generateMethodSuccessResponse($parameters, $responses)
857 if (isset($parameters[
'result']) && is_array($parameters[
'result'])) {
859 if (isset($parameters[
'result'][
'documentation'])) {
863 if (isset($parameters[
'result'][
'type'])) {
868 $specificResponseData = $parameters[
'result'][
'response_codes'][
'success'] ?? [];
870 $responseCode = $specificResponseData[
'code'] ??
'200';
872 $responseDescription = $specificResponseData[
'description'] ??
'200 Success.';
874 $responses[$responseCode][
'description'] = $responseDescription;
876 $responses[$responseCode][
'schema'] =
$schema;
889 private function generateMethodExceptionErrorResponses($exceptionClass, $responses)
896 $httpCode = WebapiException::HTTP_NOT_FOUND;
901 $httpCode = WebapiException::HTTP_UNAUTHORIZED;
905 $httpCode = WebapiException::HTTP_BAD_REQUEST;
922 $listOfAllowedServices = [];
923 foreach ($this->serviceMetadata->getServicesConfig() as $serviceName =>
$service) {
926 $listOfAllowedServices[] = $serviceName;
931 return $listOfAllowedServices;
addCustomAttributeTypes()
getQueryParamNames($name, $type, $description, $prefix='')
toLowerCaseDashSeparated($typeName)
is_subclass_of($obj, $className)
elseif(isset( $params[ 'redirect_parent']))
const UNAUTHORIZED_DESCRIPTION
generateMethodResponses($methodData)
generateSchema($requestedServiceMetadata, $requestScheme, $requestHost, $requestUri)
generatePathInfo($methodName, $httpMethodData, $tagName)
getObjectSchema($typeName, $description='')
getDefinitionReference($typeName)
generateDefinition($typeName)
isDefinitionExists($typeName)
__construct(\Magento\Webapi\Model\Cache\Type\Webapi $cache, \Magento\Framework\Reflection\TypeProcessor $typeProcessor, \Magento\Framework\Webapi\CustomAttribute\ServiceTypeListInterface $serviceTypeList, \Magento\Webapi\Model\ServiceMetadata $serviceMetadata, Authorization $authorization, SwaggerFactory $swaggerFactory, ProductMetadataInterface $productMetadata)
getServiceMetadata($serviceName)
generateTagInfo($serviceName, $serviceData)
if(!isset($_GET['name'])) $name