Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/openapi-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: OpenAPI Lint

on:
push:
branches:
- master
- dev
pull_request:
branches:
- master
- dev

jobs:
openapi-lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Start Hashtopolis server
uses: ./.github/actions/start-hashtopolis
with:
db_system: mysql
- name: Install Spectral
run: npm install -g @stoplight/spectral-cli
- name: Download JSON:API ruleset
run: curl -fsSL https://raw.githubusercontent.com/jmlue42/spectral-jsonapi-ruleset/main/.spectral.yml -o .spectral.yml
- name: Lint OpenAPI schema
run: spectral lint http://localhost:8080/api/v2/openapi.json --ruleset .spectral.yml -D
12 changes: 12 additions & 0 deletions src/inc/apiv2/common/AbstractBaseAPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,18 @@ protected function getUpdateHandlers($id, $current_user): array {
public function aggregateData(object $object, array &$includedData = [], ?array $aggregateFieldsets = null): array {
return [];
}

/**
* Return supported aggregate fieldsets/options for this endpoint.
*
* Format:
* [
* 'resourceKey' => ['option1', 'option2']
* ]
*/
public function getAggregateFieldsets(): array {
return [];
}

/**
* Take all the dba features and converts them to a list.
Expand Down
69 changes: 43 additions & 26 deletions src/inc/apiv2/common/OpenAPISchemaUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,13 @@ static function makeLinks($uri): array {
}

//TODO relationship array is unnecessarily indexed in the swagger UI
static function makeRelationships($class, $uri): array {
static function makeRelationships($relationshipsNames, $uri): array {
$properties = [];
$relationshipsNames = array_merge(array_keys($class->getToOneRelationships()), array_keys($class->getToManyRelationships()));
sort($relationshipsNames);
foreach ($relationshipsNames as $relationshipName) {
$self = $uri . "/relationships/" . $relationshipName;
$related = $uri . "/" . $relationshipName;
$properties[] = [
"properties" => [
$relationshipName => [
$properties[$relationshipName] = [
"type" => "object",
"properties" => [
"links" => [
Expand All @@ -152,9 +149,6 @@ static function makeRelationships($class, $uri): array {
]
]
]
]

]
];
}
return $properties;
Expand All @@ -166,19 +160,18 @@ static function getTUSHeader(): array {
Must always be set to `1.0.0` in compliant servers.",
"schema" => [
"type" => "string",
"enum" => "enum: ['1.0.0']"
"enum" => ['1.0.0']
]
];
}

//TODO expandables array is unnecessarily indexed in the swagger UI
static function makeExpandables($class, $container): array {
static function makeExpandables($expandables, $container): array {
$properties = [];
$expandables = array_merge($class->getToOneRelationships(), $class->getToManyRelationships());
foreach ($expandables as $expand => $expandVal) {
$expandClass = $expandVal["relationType"];
$expandApiClass = new ($container->get('classMapper')->get($expandClass))($container);
$properties[] = [
$properties[$expand] = [
"properties" => [
"id" => [
"type" => "integer"
Expand All @@ -197,20 +190,44 @@ static function makeExpandables($class, $container): array {
return $properties;
}

static function mapToProperties($map): array {
$properties = array_map(function ($value) {
return [
"type" => "string",
"default" => $value,
];
}, $map);
return [
"type" => "array",
"items" => [
"type" => "object",
"properties" => $properties
]
];
static function mapToProperties(mixed $value): array {
if (is_null($value)) {
return ["nullable" => true, "type" => "string"];
} elseif (is_bool($value)) {
return ["type" => "boolean", "example" => $value];
} elseif (is_int($value)) {
return ["type" => "integer", "example" => $value];
} elseif (is_float($value)) {
return ["type" => "number", "example" => $value];
} elseif (is_string($value)) {
return ["type" => "string", "example" => $value];
} elseif (is_array($value)) {
if (empty($value)) {
return ["type" => "array"];
}
if (array_is_list($value)) {
/* Merge properties from all items to capture the most complete schema */
$mergedProperties = [];
foreach ($value as $item) {
$itemSchema = self::mapToProperties($item);
if (isset($itemSchema['properties'])) {
$mergedProperties = array_merge($mergedProperties, $itemSchema['properties']);
}
}
$itemSchema = self::mapToProperties($value[0]);
if (!empty($mergedProperties)) {
$itemSchema['properties'] = $mergedProperties;
}
return ["type" => "array", "items" => $itemSchema];
} else {
$properties = [];
foreach ($value as $key => $val) {
$properties[$key] = self::mapToProperties($val);
}
return ["type" => "object", "properties" => $properties];
}
}
return ["type" => "string"];
}

/**
Expand Down
Loading
Loading