Skip to content

Commit cf6c4bb

Browse files
committed
feat(api): added support for OpenAPI
1 parent b3819e5 commit cf6c4bb

File tree

11 files changed

+293
-6
lines changed

11 files changed

+293
-6
lines changed

API.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# REST API v3.0 for phpMyFAQ 4.0
22

3+
> This documentation will be migrated to the OpenAPI format during the 4.0 development cycle.
4+
35
phpMyFAQ offers interfaces to access phpMyFAQ installations with other clients like an iPhone App. phpMyFAQ includes a
46
REST API and offers APIs for various services like fetching the phpMyFAQ version or doing a search against the
57
phpMyFAQ installation.

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ This is a log of major user-visible changes in each phpMyFAQ release.
1212
- changed PHP requirement to PHP 8.2 or later (Thorsten)
1313
- changed rewrite rules for Apache and nginx as mandatory requirement (Thorsten)
1414
- changed folder structure (Thorsten, Jan Harms)
15-
- (WIP) added Twig as new template engine (Thorsten)
15+
- [WIP] added Twig as new template engine (Thorsten)
1616
- added Symfony Routing (Thorsten)
1717
- added new admin configuration frontend (Thorsten)
1818
- added new admin category management frontend with full drag and drop sorting support (Thorsten)
1919
- added new admin FAQ management frontend (Thorsten)
2020
- added possibility to sort sticky FAQs (Jan Harms)
2121
- added possibility to enable/disable cookie consent (Thorsten)
2222
- added experimental online update feature (Jan Harms, Thorsten)
23-
- added REST API v3.0 (Thorsten)
23+
- [WIP] added REST API v3.0 with OpenAPI specification (Thorsten)
2424
- added Kubernetes manifest samples (OWNDOMAINHOME SAS)
2525
- added experimental import of FAQs from CSV (Jan Harms)
2626
- added CSV export of user sessions (Jan Harms)

composer.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050
"phpunit/phpunit": "11.*",
5151
"rector/rector": "^1.0.0",
5252
"squizlabs/php_codesniffer": "3.*",
53-
"symfony/yaml": "7.*"
53+
"symfony/yaml": "7.*",
54+
"zircote/swagger-php": "^4.8"
5455
},
5556
"suggest": {
5657
"ext-ldap": "*",
@@ -70,11 +71,17 @@
7071
},
7172
"sort-packages": true
7273
},
74+
"autoload": {
75+
"psr-4": {
76+
"phpMyFAQ\\": "./phpmyfaq/src/phpMyFAQ"
77+
}
78+
},
7379
"minimum-stability": "stable",
7480
"scripts": {
7581
"check": "./phpmyfaq/src/libs/bin/phpstan analyse -c phpstan.neon --memory-limit 1G",
7682
"lint": "./phpmyfaq/src/libs/bin/phpcs --standard=PSR12 --extensions=php --ignore=./phpmyfaq/src/libs/* ./phpmyfaq/src/phpMyFAQ",
7783
"lint-fix": "./phpmyfaq/src/libs/bin/phpcbf --standard=PSR12 --extensions=php --ignore=./phpmyfaq/src/libs/* ./phpmyfaq/src/phpMyFAQ",
84+
"openapi": "./phpmyfaq/src/libs/bin/openapi -b ./phpmyfaq/src/libs/autoload.php ./phpmyfaq/src/phpMyFAQ -o ./phpmyfaq/openapi.yaml",
7885
"phpstan": "./phpmyfaq/src/libs/bin/phpstan analyze --memory-limit=4G",
7986
"refactor": "./phpmyfaq/src/libs/bin/rector",
8087
"refactor:dryrun": "./phpmyfaq/src/libs/bin/rector --dry-run",

composer.lock

Lines changed: 146 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phpmyfaq/openapi.yaml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
openapi: 3.0.0
2+
info:
3+
title: 'phpMyFAQ REST API'
4+
contact:
5+
name: 'phpMyFAQ Team'
6+
7+
license:
8+
name: 'Mozilla Public Licence 2.0'
9+
url: 'https://www.mozilla.org/MPL/2.0/'
10+
version: '3.0'
11+
paths:
12+
/api/v3.0/search:
13+
get:
14+
operationId: getSearch
15+
responses:
16+
'404':
17+
description: 'If the search returns no results'
18+
content:
19+
application/json:
20+
schema: {}
21+
example: []
22+
/api/v3.0/tags:
23+
get:
24+
operationId: getTags
25+
responses:
26+
'200':
27+
description: 'Returns the tags for the given language provided by "Accept-Language".'
28+
content:
29+
application/json:
30+
schema: {}
31+
example: "[\n {\"tagId\": 4, \"tagName\": \"phpMyFAQ\", \"tagFrequency\": 3 },\n {\"tagId\": 1, \"tagName\": \"PHP 8\", \"tagFrequency\": 2 }\n ]"
32+
'404':
33+
description: 'If no tags are stored.'
34+
content:
35+
application/json:
36+
schema: {}
37+
example: []
38+
/api/v3.0/title:
39+
get:
40+
operationId: getTitle
41+
responses:
42+
'200':
43+
description: 'Returns the title of the phpMyFAQ instance as a string.'
44+
content:
45+
application/json:
46+
schema: {}
47+
example: 'phpMyFAQ Codename Pontus'
48+
/api/v3.0/version:
49+
get:
50+
operationId: getVersion
51+
responses:
52+
'200':
53+
description: 'Returns the phpMyFAQ version number as string.'
54+
content:
55+
application/json:
56+
schema: {}
57+
example: 4.0.0

phpmyfaq/src/phpMyFAQ/Controller/AbstractController.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
namespace phpMyFAQ\Controller;
1919

20+
use OpenApi\Attributes as OA;
2021
use phpMyFAQ\Configuration;
22+
use phpMyFAQ\Core\Exception;
2123
use phpMyFAQ\Enums\PermissionType;
2224
use phpMyFAQ\Template\TemplateException;
2325
use phpMyFAQ\Template\TwigWrapper;
@@ -26,12 +28,21 @@
2628
use Symfony\Component\HttpFoundation\Response;
2729
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
2830

31+
#[OA\Info(
32+
version: '3.0',
33+
title: 'phpMyFAQ REST API',
34+
contact: new OA\Contact(
35+
name: 'phpMyFAQ Team',
36+
37+
)
38+
)]
39+
#[OA\License(name: 'Mozilla Public Licence 2.0', url: 'https://www.mozilla.org/MPL/2.0/')]
2940
abstract class AbstractController
3041
{
3142
/**
3243
* Returns a Twig rendered template as response.
3344
*
34-
* @param string[] $templateVars
45+
* @param string[] $templateVars
3546
* @param Response|null $response
3647
* @throws TemplateException
3748
*/
@@ -48,6 +59,11 @@ protected function render(string $pathToTwigFile, array $templateVars = [], Resp
4859

4960
/**
5061
* Returns a JsonResponse that uses json_encode().
62+
*
63+
* @param mixed $data
64+
* @param int $status
65+
* @param string[] $headers
66+
* @return JsonResponse
5167
*/
5268
protected function json(mixed $data, int $status = 200, array $headers = []): JsonResponse
5369
{
@@ -56,6 +72,7 @@ protected function json(mixed $data, int $status = 200, array $headers = []): Js
5672

5773
/**
5874
* @throws UnauthorizedHttpException
75+
* @throws Exception
5976
*/
6077
protected function userIsAuthenticated(): void
6178
{
@@ -67,6 +84,7 @@ protected function userIsAuthenticated(): void
6784

6885
/**
6986
* @throws UnauthorizedHttpException
87+
* @throws Exception
7088
*/
7189
protected function userIsSuperAdmin(): void
7290
{
@@ -78,6 +96,7 @@ protected function userIsSuperAdmin(): void
7896

7997
/**
8098
* @throws UnauthorizedHttpException
99+
* @throws Exception
81100
*/
82101
protected function userHasGroupPermission(): void
83102
{
@@ -95,6 +114,7 @@ protected function userHasGroupPermission(): void
95114

96115
/**
97116
* @throws UnauthorizedHttpException
117+
* @throws Exception
98118
*/
99119
protected function userHasUserPermission(): void
100120
{
@@ -111,6 +131,7 @@ protected function userHasUserPermission(): void
111131

112132
/**
113133
* @throws UnauthorizedHttpException
134+
* @throws Exception
114135
*/
115136
protected function userHasPermission(PermissionType $permissionType): void
116137
{

phpmyfaq/src/phpMyFAQ/Controller/Api/SearchController.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace phpMyFAQ\Controller\Api;
1919

20+
use OpenApi\Attributes as OA;
2021
use phpMyFAQ\Category;
2122
use phpMyFAQ\Configuration;
2223
use phpMyFAQ\Faq\FaqPermission;
@@ -34,6 +35,16 @@ class SearchController
3435
/**
3536
* @throws \Exception
3637
*/
38+
#[OA\Get(
39+
path: '/api/v3.0/search',
40+
operationId: 'getSearch'
41+
)]
42+
43+
#[OA\Response(
44+
response: 404,
45+
description: 'If the search returns no results',
46+
content: new OA\JsonContent(example: []),
47+
)]
3748
public function search(Request $request): JsonResponse
3849
{
3950
$jsonResponse = new JsonResponse();

0 commit comments

Comments
 (0)