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
1,543 changes: 1,543 additions & 0 deletions .github/openapi/spectral-jsonapi.yml

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions .github/workflows/openapi-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: OpenAPI Lint

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

permissions:
contents: read

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: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Cache npm downloads
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-openapi-spectral6.15.1-redocly2.24.0
- name: Install OpenAPI tooling
run: npm install -g @stoplight/spectral-cli@6.15.1 @redocly/cli@2.24.0
- name: Download OpenAPI schema
run: wget -q http://localhost:8080/api/v2/openapi.json -O openapi.json
- name: Lint OpenAPI schema with Redocly
continue-on-error: true
run: redocly lint openapi.json
- name: Lint OpenAPI schema with Spectral
run: spectral lint openapi.json --ruleset .github/openapi/spectral-jsonapi.yml -D
2 changes: 2 additions & 0 deletions redocly.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
extends:
- recommended
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