NelmioApiDocBundle/Swagger/ModelRegistry.php

237 lines
7.2 KiB
PHP
Raw Normal View History

2014-08-07 12:06:04 -07:00
<?php
/*
* This file is part of the NelmioApiDocBundle.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
2024-10-01 15:54:04 +03:00
2014-08-07 12:06:04 -07:00
namespace Nelmio\ApiDocBundle\Swagger;
use Nelmio\ApiDocBundle\DataTypes;
/**
* Class ModelRegistry
*
* @author Bez Hermoso <bez@activelamp.com>
*/
class ModelRegistry
{
/**
* @var array
*/
2024-10-01 15:54:04 +03:00
protected $namingStrategies = [
2014-08-07 12:06:04 -07:00
'dot_notation' => 'nameDotNotation',
'last_segment_only' => 'nameLastSegmentOnly',
2024-10-01 15:54:04 +03:00
];
2014-08-07 12:06:04 -07:00
/**
* @var array
*/
2024-10-01 15:54:04 +03:00
protected $models = [];
2014-08-07 12:06:04 -07:00
2024-10-01 15:54:04 +03:00
protected $classes = [];
2014-08-07 12:06:04 -07:00
/**
* @var callable
*/
protected $namingStategy;
2024-10-01 15:54:04 +03:00
protected $typeMap = [
2014-08-07 12:06:04 -07:00
DataTypes::INTEGER => 'integer',
DataTypes::FLOAT => 'number',
DataTypes::STRING => 'string',
DataTypes::BOOLEAN => 'boolean',
DataTypes::FILE => 'string',
DataTypes::DATE => 'string',
DataTypes::DATETIME => 'string',
2024-10-01 15:54:04 +03:00
];
2014-08-07 12:06:04 -07:00
2024-10-01 15:54:04 +03:00
protected $formatMap = [
2014-08-07 12:06:04 -07:00
DataTypes::INTEGER => 'int32',
DataTypes::FLOAT => 'float',
DataTypes::FILE => 'byte',
DataTypes::DATE => 'date',
DataTypes::DATETIME => 'date-time',
2024-10-01 15:54:04 +03:00
];
2014-08-07 12:06:04 -07:00
public function __construct($namingStrategy)
{
if (!isset($this->namingStrategies[$namingStrategy])) {
throw new \InvalidArgumentException(sprintf(
'Invalid naming strategy. Choose from: %s',
json_encode(array_keys($this->namingStrategies))
));
}
2024-10-01 15:54:04 +03:00
$this->namingStategy = [$this, $this->namingStrategies[$namingStrategy]];
2014-08-07 12:06:04 -07:00
}
2024-10-01 15:54:04 +03:00
public function register($className, ?array $parameters = null, $description = '')
2014-08-07 12:06:04 -07:00
{
if (!isset($this->classes[$className])) {
2024-10-01 15:54:04 +03:00
$this->classes[$className] = [];
2014-08-07 12:06:04 -07:00
}
2024-10-01 15:54:04 +03:00
$id = call_user_func_array($this->namingStategy, [$className]);
2014-08-07 12:06:04 -07:00
if (isset($this->models[$id])) {
return $id;
}
$this->classes[$className][] = $id;
2024-10-01 15:54:04 +03:00
$model = [
2014-08-07 12:06:04 -07:00
'id' => $id,
'description' => $description,
2024-10-01 15:54:04 +03:00
];
2014-08-07 12:06:04 -07:00
if (is_array($parameters)) {
2024-10-01 15:54:04 +03:00
$required = [];
$properties = [];
2014-08-07 12:06:04 -07:00
foreach ($parameters as $name => $prop) {
2024-10-01 15:54:04 +03:00
$subParam = [];
2014-08-07 12:06:04 -07:00
2024-10-01 15:54:04 +03:00
if (DataTypes::MODEL === $prop['actualType']) {
2014-08-07 12:06:04 -07:00
$subParam['$ref'] = $this->register(
$prop['subType'],
2024-10-01 15:54:04 +03:00
$prop['children'] ?? null,
2014-08-07 12:06:04 -07:00
$prop['description'] ?: $prop['dataType']
);
} else {
$type = null;
$format = null;
$items = null;
$enum = null;
$ref = null;
if (isset($this->typeMap[$prop['actualType']])) {
$type = $this->typeMap[$prop['actualType']];
} else {
switch ($prop['actualType']) {
case DataTypes::ENUM:
$type = 'string';
if (isset($prop['format'])) {
$enum = array_keys(json_decode($prop['format'], true));
}
break;
case DataTypes::COLLECTION:
$type = 'array';
2024-10-01 15:54:04 +03:00
if (null === $prop['subType']) {
$items = [
'type' => 'string',
];
} elseif (isset($this->typeMap[$prop['subType']])) {
$items = [
'type' => $this->typeMap[$prop['subType']],
];
} elseif (!isset($this->typeMap[$prop['subType']])) {
$items = [
'$ref' => $this->register(
$prop['subType'],
$prop['children'] ?? null,
$prop['description'] ?: $prop['dataType']
),
];
}
2014-08-07 12:06:04 -07:00
/* @TODO: Handle recursion if subtype is a model. */
break;
case DataTypes::MODEL:
$ref = $this->register(
$prop['subType'],
2024-10-01 15:54:04 +03:00
$prop['children'] ?? null,
2014-08-07 12:06:04 -07:00
$prop['description'] ?: $prop['dataType']
);
$type = $ref;
/* @TODO: Handle recursion. */
break;
}
}
if (isset($this->formatMap[$prop['actualType']])) {
$format = $this->formatMap[$prop['actualType']];
}
2024-10-01 15:54:04 +03:00
$subParam = [
2014-08-07 12:06:04 -07:00
'type' => $type,
2024-10-01 15:54:04 +03:00
'description' => false === empty($prop['description']) ? (string) $prop['description'] : $prop['dataType'],
];
2014-08-07 12:06:04 -07:00
2024-10-01 15:54:04 +03:00
if (null !== $format) {
2014-08-07 12:06:04 -07:00
$subParam['format'] = $format;
}
2024-10-01 15:54:04 +03:00
if (null !== $enum) {
2014-08-07 12:06:04 -07:00
$subParam['enum'] = $enum;
}
2024-10-01 15:54:04 +03:00
if (null !== $ref) {
2014-08-07 12:06:04 -07:00
$subParam['$ref'] = $ref;
}
2024-10-01 15:54:04 +03:00
if (null !== $items) {
2014-08-07 12:06:04 -07:00
$subParam['items'] = $items;
}
if ($prop['required']) {
$required[] = $name;
}
}
$properties[$name] = $subParam;
}
$model['properties'] = $properties;
$model['required'] = $required;
$this->models[$id] = $model;
}
return $id;
}
public function nameDotNotation($className)
{
/*
* Converts \Fully\Qualified\Class\Name to Fully.Qualified.Class.Name
* "[...]" in aliased and non-aliased collections preserved.
2014-08-07 12:06:04 -07:00
*/
$id = preg_replace('#(\\\|[^A-Za-z0-9\[\]])#', '.', $className);
2024-10-01 15:54:04 +03:00
// Replace duplicate dots.
2014-08-07 12:06:04 -07:00
$id = preg_replace('/\.+/', '.', $id);
2024-10-01 15:54:04 +03:00
// Replace trailing dots.
2014-08-07 12:06:04 -07:00
$id = preg_replace('/^\./', '', $id);
return $id;
}
public function nameLastSegmentOnly($className)
{
/*
* Converts \Fully\Qualified\ClassName to ClassName
*/
$segments = explode('\\', $className);
$id = end($segments);
return $id;
}
public function getModels()
{
return $this->models;
}
2014-08-07 12:23:55 -07:00
2024-10-01 15:54:04 +03:00
public function clear(): void
2014-08-07 12:23:55 -07:00
{
2024-10-01 15:54:04 +03:00
$this->models = [];
$this->classes = [];
2014-08-07 12:23:55 -07:00
}
2014-08-07 12:06:04 -07:00
}