# API
The application is meant to be an API.
Any function can be a route. It is registered in the application.
## Get Started
- You can register new route with the following functions : `Application::addRoute` (generic) and `Application::connectRoutes` (for a whole class)
- The registered route is saved as a `MMO\core\attribute\APIRoute` for the web, and as a `\MMO\core\attributes\Command` for the command line.
- `Application::connectRoutes` registers all methods that have one of the previous method's attribute.
- You can auto connect route through the application's configuration: (here we register `MMO\core\controllers\RepositoryController` with some parameters)
```json
{
"MMO\\core\\Application": {
"routes": {
"MMO\\core\\controllers\\RepositoryController": {}
}
},
"MMO\\core\\controllers\\RepositoryController": {
"repositories": {"main": {"$" : "#repository"}}
},
"repository": {
"$": "MMO\\core\\entities\\JsonRepository",
"filenames": {
"users": "users.json"
},
"collections": {
"users": "MMO\\oauth\\entities\\User"
}
}
}
```
## Workflow
1. When routes have been registered you can call `\MMO\run()` or `Application::run()` that will trigger the routing of the current or given request and exit the application.
2. The application create a `MMO\core\server\Route` (the only one and accessible through `Application::getRoute()`) that holds all the information of the current routing.
It has the current `\MMO\core\server\Request`, the current `\MMO\core\server\Response`, and all the functions to call (these functions are called *middleware*).
Keep in mind that a request or a response is immutable, so whenever you want to change their properties, you need to save the new instance back in the route.
3. The application look through all its registered route and check if they match the current request. If it is the case, it is added to the current route.
4. The application dispatch the route so you can modify it using the event registration `Route::AddListener`.
This is normally when you check for the current user, rights to access, you remove middlewares, add information on the request, etc...
5. The route is executed (each middleware is called). The middleware can optionally return a Response or an array (that will be added to the current response body).
6. the last response set in the route is returned to the server.
> NOTE: A response is only a container for the actual data to send. You access these data through `Response::getParsedBody()`
## Implementing a Controller
A controller is a module that uses the trait `\MMO\core\classes\tWithRoutes`. This trait gives static functions that ONLY works
if the controller has been registered in the application with `Application::connectRoutes()` or through the configuration.
- `Routes(): array` gives a list of registered routes.
- `Route(string $method): ?APIRoute` gives information aboute the registered route for a method.
- `Url(string $method, ?array $data = null): string` gives the url to access a route. $data are the data to pass to the url is it contains parameters.
- `Link(string $method, ?array $data = null): Link` gives a `MMO\core\server\Link` for a given method. This link can be used to add a menu in the client :
```php
Response::AddListener(function (Response $response) {
if ($response->isHtml()) {
$response->getParsedBody()->addMenu(MyController::Link('myMethod'));
}
});
```
There can be only one active controller. The first controller to have a matching route takes effect.
You can affect this order using the `order` parameter of an APIRoute. (order is ASC. so a route with order 10 is executed before the one with order 20)
## APIRoute
The method/function attribute `\MMO\core\attributes\APIRoute` or `\MMO\core\attributes\Command` is used to declare a route.
The attribute has the following parameters:
### Matching parameters
- `string $url`: the relative url of the route with an optional method. ex: `POST|mypath/{user:string}/{id:int}`.
- With no method, the route match for all methods.
- You can define `*` in the path, that will match any part. ex: `mypath/*/user` match `mypath/test/user` and `mypath/hello/user` but NOT `mypath/test/hello/user`.
- To match multiple parts, you can use `**`. This only works at the end of an url. ex: `mypath/**` match `mypath/test/hello/user`. `mypath/**/user` is NOT allowed.
- Parameters are declared using moustache (curly brackets). `{user}` will capture the parameter `user` and will store it in the request.
You can access the parameter using `Route::get('user')` or `Request::getAttribute('user')`
You can specify a type using a semicolon `{user:string}`. Allowed types can be defined using the static function `\MMO\core\schemas\Schema::RegisterGlobalType`.
The primitive types defined by the json schema are available by default.
- `?array $body = null`: the parameters to catch from the body in a POST/PUT/DELETE request.
- for each key that you want to capture, you can define a schema to validate the input or a template with moustache (works like the url).
- @see `\MMO\core\strings\matchTpl` for more information.
### Functional parameters
- `array $mediaTypes = []`: the allowed media types for the response. You SHOULD only declare one, so a response can automatically be created when the controller is executed.
- `int $order = 0`: the order to execute the controller
### API documentation parameters
- `?string $summary = null`: the summary to use in the API documentation.
- `iSchema|array $schema = []`: the schema to use in the API documentation.
- `string $description = null`: the description to use in the API documentation
- `?array $tags = null`: a list of tags to use in the API documentation
## References
### See also
## Tags
<#event>, <#signal>, <#API>, <#controller>, <#middleware>