Skip to content
Merged
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
44 changes: 44 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,50 @@ have a chance of keeping on top of things:
11. Together with your reviewer, polish your changes until they are ready to be
merged.

## API Documentation with Swagger

Controllers are annotated with the [`OpenAPI`](https://swagger.io/docs/specification/about/) specification using the `PHPDoc` implementation from [zircote/swagger-php](https://github.com/zircote/swagger-php).

If you add or modify existing annotations, you should run `composer generate-openapi` to have the updated version of the API Docs.


### Details on `composer generate-openapi`

`composer generate-openapi` basically runs `vendor/bin/openapi -o docs/swagger/openapi.json --format json src"` defined in the scripts section of `composer.json` which inturn generates the `OpenAPI` specification file `openapi.json` in the `docs/swagger` directory and then copies the documentation and `swagger-ui` files to `public/docs`.


### Swagger UI

[Swagger UI](https://github.com/swagger-api/swagger-ui) is used to visualize generated `OpenAPI` documentation and is served at `{root-url}/docs` for example `localhost:8000/docs`.

#### Updating Swagger UI

We use`swagger-ui-dist` which is the compiled version of swagger UI for server side projects. It's simply a copy of the `dist` directory from the[Swagger UI Repo](https://github.com/swagger-api/swagger-ui)) stored `public/docs`.

So if there are updates in the UI we would like to have, the fastest way to update our copy of swagger UI would be to clone the entire swagger UI [repository](https://github.com/swagger-api/swagger-ui) and copy the contents of `dist` to `public/docs` and make the required changes to `public/docs/index.html`. That includes making sure the assets (javascript and css) are pointing to the right place (`/docs/`) and that `SwaggerUIBundle` is referencing `public/docs/openapi.json` correctly as shown bellow;

```js
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "/docs/openapi.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
// End Swagger UI call region

window.ui = ui;
};
```


## Unit-test your changes

Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ Please install this package via Composer from within the
[phpList base distribution](https://github.com/phpList/base-distribution),
which also has more detailed installation instructions in the README.

## API Documentation

Visit `/docs` endpoint to access the full interactive documentation for `phpList/rest-api`.

Look at the **"API Documentation with Swagger"** section in the [contribution guide](.github/CONTRIBUTING.md) for more information on API documenation.

## Local demo with Postman

You can try out the API using pre-prepared requests and the Postman GUI
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"php": "^7.2|^8.0",
"phplist/core": "^v4.0.0-alpha5",
"friendsofsymfony/rest-bundle": "^2.8.6",
"sensio/framework-extra-bundle": "5.1.0"
"sensio/framework-extra-bundle": "5.1.0",
"zircote/swagger-php": "^3.1"
},
"require-dev": {
"phpunit/phpunit": "^6.5.14",
Expand Down
267 changes: 267 additions & 0 deletions src/Controller/ListController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use PhpList\Core\Security\Authentication;
use PhpList\RestBundle\Controller\Traits\AuthenticationTrait;
use Symfony\Component\HttpFoundation\Request;
use OpenApi\Annotations as OA;

/**
* This controller provides REST API access to subscriber lists.
Expand Down Expand Up @@ -40,6 +41,63 @@ public function __construct(Authentication $authentication, SubscriberListReposi
/**
* Gets a list of all subscriber lists.
*
* @OA\Get(
* path="/api/v2/lists",
* tags={"lists"},
* summary="Gets a list of all subscriber lists.",
* description="Returns a json list of all subscriber lists.",
* @OA\Parameter(
* name="session",
* in="header",
* description="Session ID obtained from authentication",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Response(
* response=201,
* description="Success",
* @OA\JsonContent(
* type="object",
* example={
* {
* "name": "News",
* "description": "News (and some fun stuff)",
* "creation_date": "2016-06-22T15:01:17+00:00",
* "list_position": 12,
* "subject_prefix": "phpList",
* "public": true,
* "category": "news",
* "id": 1
* },
* {
* "name": "More news",
* "description": "",
* "creation_date": "2016-06-22T15:01:17+00:00",
* "list_position": 12,
* "subject_prefix": "",
* "public": true,
* "category": "",
* "id": 2
* }
* }
* )
* ),
* @OA\Response(
* response=403,
* description="Failure",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* example="No valid session key was provided as basic auth password.")
* )
* )
* )
*
*
*
* @param Request $request
*
* @return View
Expand All @@ -54,6 +112,68 @@ public function cgetAction(Request $request): View
/**
* Gets a subscriber list.
*
* @OA\Get(
* path="/api/v2/lists/{list}",
* tags={"lists"},
* summary="Gets a subscriber list.",
* description="Returns a single subscriber lists with specified ID",
* @OA\Parameter(
* name="list",
* in="path",
* description="List ID",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Parameter(
* name="session",
* in="header",
* description="Session ID obtained from authentication",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Response(
* response=200,
* description="Success",
* @OA\JsonContent(
* type="object",
* example={
* {
* "name": "News",
* "description": "News (and some fun stuff)",
* "creation_date": "2016-06-22T15:01:17+00:00",
* "list_position": 12,
* "subject_prefix": "phpList",
* "public": true,
* "category": "news",
* "id": 1
* }
* }
* )
* ),
* @OA\Response(
* response=403,
* description="Failure",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* example="No valid session key was provided as basic auth password."
* )
* )
* ),
* @OA\Response(
* response=404,
* description="Failure",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="There is no list with that ID.")
* )
* )
* )
*
* @param Request $request
* @param SubscriberList $list
*
Expand All @@ -69,6 +189,46 @@ public function getAction(Request $request, SubscriberList $list): View
/**
* Deletes a subscriber list.
*
*
* @OA\Delete(
* path="/api/v2/lists/{list}",
* tags={"lists"},
* summary="Deletes a list.",
* description="Deletes a single subscriber list passed as",
* @OA\Parameter(
* name="session",
* in="header",
* description="Session ID",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Response(
* response=200,
* description="Success"
* ),
* @OA\Response(
* response=403,
* description="Failure",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* example="No valid session key was provided as basic auth password or You do not have access to this session."
* )
* )
* ),
* @OA\Response(
* response=404,
* description="Failure",
* @OA\JsonContent(
* @OA\Property(property="message", type="string", example="There is no session with that ID.")
* )
* )
* )
*
*
* @param Request $request
* @param SubscriberList $list
*
Expand All @@ -86,6 +246,74 @@ public function deleteAction(Request $request, SubscriberList $list): View
/**
* Gets a list of all subscribers (members) of a subscriber list.
*
*
* @OA\Get(
* path="/api/v2/lists/{list}/members",
* tags={"lists"},
* summary="Gets a list of all subscribers (members) of a subscriber list.",
* description="Returns a json list of all subscriber lists.",
* @OA\Parameter(
* name="session",
* in="header",
* description="Session ID obtained from authentication",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Parameter(
* name="list",
* in="path",
* description="List ID",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Response(
* response=200,
* description="Success",
* @OA\JsonContent(
* type="object",
* example={
* {
* "creation_date": "2016-07-22T15:01:17+00:00",
* "email": "oliver@example.com",
* "confirmed": true,
* "blacklisted": true,
* "bounce_count": 17,
* "unique_id": "95feb7fe7e06e6c11ca8d0c48cb46e89",
* "html_email": true,
* "disabled": true,
* "id": 1,
* },
* {
* "creation_date": "2017-07-22T15:12:17+00:00",
* "email": "sam@example.com",
* "confirmed": true,
* "blacklisted": false,
* "bounce_count": 1,
* "unique_id": "95feb7fe7e06e6c11ca8d0c48cb4616d",
* "html_email": false,
* "disabled": false,
* "id": 2,
* }
* }
* )
* ),
* @OA\Response(
* response=403,
* description="Failure",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* example="No valid session key was provided as basic auth password.")
* )
* )
* )
*
*
* @param Request $request
* @param SubscriberList $list
*
Expand All @@ -101,6 +329,45 @@ public function getMembersAction(Request $request, SubscriberList $list): View
/**
* Gets the total number of subscribers of a list.
*
* @OA\Get(
* path="/api/v2/lists/{list}/count",
* tags={"lists"},
* summary="Gets the total number of subscribers of a list",
* description="Returns a count of all subscribers in a given list.",
* @OA\Parameter(
* name="session",
* in="header",
* description="Session ID obtained from authentication",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Parameter(
* name="list",
* in="path",
* description="List ID",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Response(
* response=200,
* description="Success"
* ),
* @OA\Response(
* response=403,
* description="Failure",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* example="No valid session key was provided as basic auth password.")
* )
* )
* )
*
* @param Request $request
* @param SubscriberList $list
*
Expand Down
Loading