diff --git a/CHANGELOG.md b/CHANGELOG.md index b5d7c530..aeeb3851 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed +## 4.8.0 - Saturday, 2 May 2020 ([compare to previous](https://github.com/mpociot/laravel-apidoc-generator/compare/4.7.0...4.8.0)) +### Added +- Support @hideFromAPIDocumentation on controllers. (https://github.com/mpociot/laravel-apidoc-generator/pull/745) +- Allow strategies to return null. (https://github.com/mpociot/laravel-apidoc-generator/pull/739) + +## 4.7.0 - Sunday, 12 April 2020 ([compare to previous](https://github.com/mpociot/laravel-apidoc-generator/compare/4.6.0...4.7.0)) +### Added +- Support for Laravel Vapor. (https://github.com/mpociot/laravel-apidoc-generator/pull/729) +- Allow customization of static output path. (https://github.com/mpociot/laravel-apidoc-generator/pull/730) + +## 4.6.0 - Wednesday, 8 April 2020 ([compare to previous](https://github.com/mpociot/laravel-apidoc-generator/compare/4.5.1...4.6.0)) +### Added +- Allow `@authenticated` to be set at controller level. (https://github.com/mpociot/laravel-apidoc-generator/pull/726) + +## 4.5.1 - Saturday, 4 April 2020 ([compare to previous](https://github.com/mpociot/laravel-apidoc-generator/compare/4.5.0...4.5.1)) +### Fixed +- Fix version constraint...again. (https://github.com/mpociot/laravel-apidoc-generator/pull/725) + ## 4.5.0 - Tuesday, 31 March 2020 ([compare to previous](https://github.com/mpociot/laravel-apidoc-generator/compare/4.4.3...4.5.0)) ### Fixed -- Fix version constraints preventin installation on some Laravel 7 installations. +- Fix version constraints preventing installation on some Laravel 7 installations. ## 4.4.3 - Thursday, 26 March 2020 ([compare to previous](https://github.com/mpociot/laravel-apidoc-generator/compare/4.4.2...4.4.3)) ### Fixed diff --git a/README.md b/README.md index f84f93f9..f5c6ed8f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Laravel API Documentation Generator -Automatically generate your API documentation from your existing Laravel/Lumen/[Dingo](https://github.com/dingo/api) routes. [Here's what the output looks like](https://shalvah.me/TheCensorshipAPI/). +Automatically generate your API documentation from your existing Laravel/Lumen/[Dingo](https://github.com/dingo/api) routes. `php artisan apidoc:generate` @@ -44,7 +44,7 @@ $app->configure('apidoc'); ``` ## Documentation -Check out the documentation at [ReadTheDocs](http://laravel-apidoc-generator.rtfd.io/). Don't forget to check out the [migration guide](https://laravel-apidoc-generator.rtfd.io/en/latest/migrating.html) if you're coming from v3 to v4. +Check out the documentation at the [Beyond Code homepage](https://beyondco.de/docs/laravel-apidoc-generator/). ### License diff --git a/composer.json b/composer.json index 407f80d5..9249c973 100644 --- a/composer.json +++ b/composer.json @@ -18,19 +18,19 @@ "php": ">=7.2.0", "ext-json": "*", "fzaninotto/faker": "^1.8", - "illuminate/console": "^5.7|^6.0|^7.0", - "illuminate/routing": "^5.7|^6.0|^7.0", - "illuminate/support": "^5.7|^6.0|^7.0", + "illuminate/console": "^5.7|^6.0|^7.0|^8.0", + "illuminate/routing": "^5.7|^6.0|^7.0|^8.0", + "illuminate/support": "^5.7|^6.0|^7.0|^8.0", "league/flysystem": "^1.0", "mpociot/documentarian": "^0.4.0", "mpociot/reflection-docblock": "^1.0.1", - "nunomaduro/collision": "^3.0|^4.0", - "ramsey/uuid": "^3.8|4.0", + "nunomaduro/collision": "^3.0|^4.0|^5.0", + "ramsey/uuid": "^3.8|^4.0", "symfony/var-exporter": "^4.0|^5.0" }, "require-dev": { "dms/phpunit-arraysubset-asserts": "^0.1.0", - "laravel/lumen-framework": "^5.7|^6.0|^7.0", + "laravel/lumen-framework": "^5.7|^6.0|^7.0|^8.0", "league/fractal": "^0.19.0", "orchestra/testbench": "^3.7|^4.0|^5.0", "phpstan/phpstan": "^0.11.15", diff --git a/config/apidoc.php b/config/apidoc.php index 80c5e73d..8ae737be 100644 --- a/config/apidoc.php +++ b/config/apidoc.php @@ -9,6 +9,11 @@ */ 'type' => 'static', + /* + * Static output folder: HTML documentation and assets will be generated in this folder. + */ + 'output_folder' => 'public/docs', + /* * Settings for `laravel` type output. */ @@ -37,6 +42,13 @@ */ 'router' => 'laravel', + /* + * The storage to be used when generating assets. + * By default, uses 'local'. If you are using Laravel Vapor, please use S3 and make sure + * the correct bucket is correctly configured in the .env file + */ + 'storage' => 'local', + /* * The base URL to be used in examples and the Postman collection. * By default, this will be the value of config('app.url'). diff --git a/dingo.composer.json b/dingo.composer.json index 56b45a23..83004b63 100644 --- a/dingo.composer.json +++ b/dingo.composer.json @@ -18,14 +18,14 @@ "php": ">=7.2.0", "ext-json": "*", "fzaninotto/faker": "^1.8", - "illuminate/console": "^5.7|^6.0|^7.0", - "illuminate/routing": "^5.7|^6.0|^7.0", - "illuminate/support": "^5.7|^6.0|^7.0", + "illuminate/console": "^5.7|^6.0|^7.0|^8.0", + "illuminate/routing": "^5.7|^6.0|^7.0|^8.0", + "illuminate/support": "^5.7|^6.0|^7.0|^8.0", "league/flysystem": "^1.0", "mpociot/documentarian": "^0.4.0", "mpociot/reflection-docblock": "^1.0.1", - "nunomaduro/collision": "^3.0|^4.0", - "ramsey/uuid": "^3.8|4.0", + "nunomaduro/collision": "^3.0|^4.0|^5.0", + "ramsey/uuid": "^3.8|^4.0", "symfony/var-exporter": "^4.0|^5.0" }, "require-dev": { diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index 298ea9e2..00000000 --- a/docs/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/_index.md b/docs/_index.md new file mode 100644 index 00000000..8dcb342b --- /dev/null +++ b/docs/_index.md @@ -0,0 +1,4 @@ +--- +packageName: Laravel API Documentation Generator +githubUrl: https://github.com/mpociot/laravel-apidoc-generator +--- \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index 58bf09e5..00000000 --- a/docs/conf.py +++ /dev/null @@ -1,61 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# http://www.sphinx-doc.org/en/master/config - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) -import recommonmark -from recommonmark.transform import AutoStructify - -# -- Project information ----------------------------------------------------- - -project = 'laravel-apidoc-generator' -copyright = '2019, Marcel Pociot' -author = 'Marcel Pociot' - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = ['recommonmark'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'sphinx_rtd_theme' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -master_doc = 'index' - -# app setup hook -def setup(app): - app.add_config_value('recommonmark_config', { - 'auto_toc_tree_section': 'Contents', - }, True) - app.add_transform(AutoStructify) diff --git a/docs/extending/_index.md b/docs/extending/_index.md new file mode 100644 index 00000000..cf3041a7 --- /dev/null +++ b/docs/extending/_index.md @@ -0,0 +1,4 @@ +--- +title: Extending +order: 2 +--- diff --git a/docs/plugins.md b/docs/extending/plugins.md similarity index 99% rename from docs/plugins.md rename to docs/extending/plugins.md index 66d44671..ac3b343a 100644 --- a/docs/plugins.md +++ b/docs/extending/plugins.md @@ -1,3 +1,7 @@ +--- +title: Plugins +order: 1 +--- # Extending functionality with plugins You can use plugins to alter how the Generator fetches data about your routes. For instance, suppose all your routes have a body parameter `organizationId`, and you don't want to annotate this with `@queryParam` on each method. You can create a plugin that adds this to all your body parameters. Let's see how to do this. @@ -29,8 +33,6 @@ The `__invoke` method of the strategy is where you perform your actions and retu Here's what your strategy in our example would look like: ```php - In both instances, the source markdown file will be generated in `resources/docs/source`. -## `laravel` +### laravel If you're using `laravel` type output, this package can automatically set up an endpoint for you to view your generated docs. You can configure this here. -### `autoload` -Set this to `true` if you want the documentation endpoint to be automatically set up for you. Default: `false` (*note that this will change in the next major release*) +### autoload +Set this to `true` if you want the documentation endpoint to be automatically set up for you. Default: `false` You may, of course, use your own routing instead of using `autoload`. -### `docs_url` +### docs_url The path for the documentation endpoint (if `autoload` is true). Your Postman collection (if you have that enabled) will be at this path + '.json' (eg `/doc.json`). Default: `/doc` > Note: There is currently a known issue with using `/docs` as the path for `laravel` docs. You should not use it, as it conflicts with the folder structure in the `public` folder and may confuse the webserver. -### `middleware` +## middleware Here, you can specify middleware to be attached to the documentation endpoint (if `autoload` is true). -## `router` +## router The router to use when processing your routes (can be Laravel or Dingo. Defaults to **Laravel**) -## `base_url` +## base_url The base URL to be used in examples and the Postman collection. By default, this will be the value of config('app.url'). -## `postman` +## postman This package can automatically generate a Postman collection for your routes, along with the documentation. This section is where you can configure (or disable) that. -- For `static` docs (see [type](#type)), the collection will be created in `public/docs/collection.json`, so it can be accessed by visiting {yourapp.domain}/docs/colllection.json. -- For `laravel` docs, the collection will be generated to `storage/app/apidoc/collection.json`. The `ApiDoc::routes()` helper will add a `/docs.json` endpoint to fetch it.. -### `enabled` +For `static` docs (see [type](#type)), the collection will be created in `public/docs/collection.json`, so it can be accessed by visiting {yourapp.domain}/docs/colllection.json. + +For `laravel` docs, the collection will be generated to `storage/app/apidoc/collection.json`. The `ApiDoc::routes()` helper will add a `/docs.json` endpoint to fetch it.. + +### enabled Whether or not to generate a Postman API collection. Default: **true** -### `name` +### name The name for the exported Postman collection. If you leave this as null, this package will default to `config('app.name')." API"`. -### `description` +### description The description for the generated Postman collection. -## `logo` +## logo You can specify a custom logo to be used on the generated documentation. Set the `logo` option to an absolute path pointing to your logo file. For example: ``` 'logo' => resource_path('views') . '/api/logo.png' @@ -53,23 +63,24 @@ You can specify a custom logo to be used on the generated documentation. Set the If you want to use this, please note that the image size must be 230 x 52. -## `default_group` -When [documenting your api](documenting.md), you use `@group` annotations to group API endpoints. Endpoints which do not have a group annotation will be grouped under the `default_group`. Defaults to **"general"**. +## default_group +When [documenting your api](/docs/laravel-apidoc-generator/getting-started/documenting-your-api), you use `@group` annotations to group API endpoints. Endpoints which do not have a group annotation will be grouped under the `default_group`. Defaults to **"general"**. -## `example_languages` -For each endpoint, an example request is shown in each of the languages specified in this array. Currently only `bash`, `javascript`, `php` and `python` are supported. You can add your own language, but you must also define the corresponding view (see [Specifying languages for examples](generating-documentation.html#specifying-language-for-examples)). Default: `["bash", "javascript"]` +## example_languages +For each endpoint, an example request is shown in each of the languages specified in this array. Currently only `bash`, `javascript`, `php` and `python` are supported. You can add your own language, but you must also define the corresponding view (see [Specifying languages for examples](/docs/laravel-apidoc-generator/getting-started/generating-documentation)). Default: `["bash", "javascript"]` -## `faker_seed` -When generating example requests, this package uses fzanninoto/faker to generate random values. If you would like the package to generate the same example values for parameters on each run, set this to any number (eg. 1234). (Note: alternatively, you can set example values for parameters when [documenting them.](documenting.html#specifying-request-parameters)) +## faker_seed +When generating example requests, this package uses fzanninoto/faker to generate random values. If you would like the package to generate the same example values for parameters on each run, set this to any number (eg. 1234). (Note: alternatively, you can set example values for parameters when [documenting them.](/docs/laravel-apidoc-generator/getting-started/documenting-your-api)) -## `routeMatcher` +## routeMatcher The route matcher class provides the algorithm that determines what routes should be documented. The default matcher used is the included `\Mpociot\ApiDoc\Matching\RouteMatcher::class`, and you can provide your own custom implementation if you wish to programmatically change the algorithm. The provided matcher must be an instance of the `RouteMatcherInterface`. -## `fractal` -This section only applies if you're using [Transformers]() for your API, and documenting responses with `@transformer` and `@transformerCollection`. Here, you configure how responses are transformed. +## fractal +This section only applies if you're using Transformers for your API, and documenting responses with `@transformer` and `@transformerCollection`. Here, you configure how responses are transformed. > Note: using transformers requires league/fractal package. Run `composer require league/fractal to install + ### serializer If you are using a custom serializer with league/fractal, you can specify it here. league/fractal comes with the following serializers: - \League\Fractal\Serializer\ArraySerializer::class @@ -78,7 +89,7 @@ If you are using a custom serializer with league/fractal, you can specify it he Leave this as null to use no serializer or return a simple JSON. -## `routes` +## routes The `routes` section is an array of items, describing what routes in your application that should have documentation generated for them. Each item in the array contains rules about what routes belong in that group, and what rules to apply to them. This allows you to apply different settings to different routes. > Note: This package does not work with Closure-based routes. If you want your route to be captured by this package, you need a controller. @@ -86,8 +97,6 @@ The `routes` section is an array of items, describing what routes in your applic Each item in the `routes` array (a route group) has keys which are explained below. We'll use this sample route definition for a Laravel app to demonstrate them: ```php - 'api.acme.co'], function () { Route::get('/apps', 'AppController@listApps') ->name('apps.list'); @@ -112,14 +121,13 @@ Route::group(['domain' => 'status.acme.co'], function () { }); ``` -### `match` +### match In this section, you define the rules that will be used to determine what routes in your application fall into this group. There are three kinds of rules defined here (keys in the `match` array): -#### `domains` +### domains This key takes an array of domain names as its value. Only routes which are defined on the domains specified here will be matched as part of this group. For instance, in our sample routes above, we may wish to apply different settings to documentation based on the domains. For instance, the routes on the `api.acme.co` domain need authentication, while those on the other domains do not. We can separate them into two groups like this: ```php - The `domains` and `prefixes` keys are both required for all route groups. -#### `versions` +### versions > This section only applies if you're using Dingo Router When using Dingo's Router, all routes must be specified inside versions. This means that you must specify the versions to be matched along with the domains and prefixes when describing a route group. Note that wildcards in `versions` are not supported; you must list out all your versions explicitly. Example: ```php - ['users/*']` to exclude all routes with URLs matching the pattern. -### `apply` +### apply After defining the routes in `match` (and `include` or `exclude`), `apply` is where you specify the settings to be applied to those routes when generating documentation. There are a bunch of settings you can tweak here: -#### `headers` -Like we've demonstrated above, any headers you specify here will be added to the headers shown in the example requests in your documentation. They will also be included in ["response calls"](documenting.html#generating-responses-automatically). Headers are specified as key => value strings. +### headers +Like we've demonstrated above, any headers you specify here will be added to the headers shown in the example requests in your documentation. They will also be included in ["response calls"](/docs/laravel-apidoc-generator/getting-started/documenting-your-api). Headers are specified as key => value strings. -#### `response_calls` -These are the settings that will be applied when making ["response calls"](documenting.html#generating-responses-automatically). See the linked section for details. +### response_calls +These are the settings that will be applied when making ["response calls"](/docs/laravel-apidoc-generator/getting-started/documenting-your-api). See the linked section for details. diff --git a/docs/documenting.md b/docs/getting-started/documenting-your-api.md similarity index 92% rename from docs/documenting.md rename to docs/getting-started/documenting-your-api.md index 2ac68490..c11a4600 100644 --- a/docs/documenting.md +++ b/docs/getting-started/documenting-your-api.md @@ -1,3 +1,7 @@ +--- +title: Documenting Your API +order: 4 +--- # Documenting Your API This package generates documentation from your code using mainly annotations (in doc block comments). @@ -45,7 +49,7 @@ class UserController extends Controller **Result:** -![Doc block result](http://headsquaredsoftware.co.uk/images/api_generator_docblock.png) +![Doc block result](/img/api_generator_docblock.png) ## Specifying request parameters To specify a list of valid parameters your API route accepts, use the `@urlParam`, `@bodyParam` and `@queryParam` annotations. @@ -92,12 +96,6 @@ public function listPosts() They will be included in the generated documentation text and example requests. -**Result:** - -![](body_params_1.png) - -![](body_params_2.png) - ### Example parameters For each parameter in your request, this package will generate a random value to be used in the example requests. If you'd like to specify an example value, you can do so by adding `Example: your-example` to the end of your description. For instance: @@ -114,11 +112,11 @@ For each parameter in your request, this package will generate a random value to You can also exclude a particular parameter from the generated examples (for all languages) by annotating it with `No-example`. For instance: ```php - /** - * @queryParam location_id required The id of the location. Example: 1 - * @queryParam user_id required The id of the user. No-example - * @queryParam page required The page number. Example: 4 - */ + /** + * @queryParam location_id required The id of the location. Example: 1 + * @queryParam user_id required The id of the user. No-example + * @queryParam page required The page number. Example: 4 + */ ``` Outputs: ```bash @@ -151,6 +149,41 @@ public function createPost(MyRequest $request) ## Indicating authentication status You can use the `@authenticated` annotation on a method to indicate if the endpoint is authenticated. A "Requires authentication" badge will be added to that route in the generated documentation. +Just like `@group` annotation, you can also specify an `@authenticated` on a single method to override the authenticated status defined at the controller level. + +```php +/** + * @authenticated + * + * APIs for managing users + */ +class UserController extends Controller +{ + + /** + * Create a user + * + * [Insert optional longer description of the API endpoint here.] + * + */ + public function createUser() + { + + } + + /** + * @group Account management + * + */ + public function changePassword() + { + + } +} +``` + +Now all the methods under this controller will have "Requires authentication" badge enabled. + ## Providing an example response You can provide an example response for a route. This will be displayed in the examples section. There are several ways of doing this. diff --git a/docs/generating-documentation.md b/docs/getting-started/generating-documentation.md similarity index 86% rename from docs/generating-documentation.md rename to docs/getting-started/generating-documentation.md index 84f1570f..4deecda9 100644 --- a/docs/generating-documentation.md +++ b/docs/getting-started/generating-documentation.md @@ -1,10 +1,13 @@ +--- +title: Generating Documentation +order: 5 +--- # Generating Documentation To generate your API documentation, use the `apidoc:generate` artisan command. ```sh php artisan apidoc:generate - ``` It will generate documentation using your specified configuration. The documentation will be generated as static HTML and CSS assets within the specified output folder. @@ -23,7 +26,7 @@ The base URL used in the Postman collection will be the value of the `base_url` ## Manually modifying the content of the generated documentation If you want to modify the content of your generated documentation without changing the routes, go ahead and edit the generated `index.md` file. -This file is located in the `source` folder of your `output` directory (see [configuration](config.html#output)), so by default, this is `public/docs/source/index.md`. +This file is located in the `source` folder of your `output` directory (see configuration), so by default, this is `public/docs/source/index.md`. After editing the markdown file, you can use the `apidoc:rebuild` command to rebuild your documentation into HTML. @@ -37,7 +40,7 @@ php artisan apidoc:rebuild The contents of `prepend.md` will be added after the front matter and info text, while the contents of `append.md` will be added at the end of the document. ## Specifying language for examples - For each endpoint, an example request is shown in [each language configured](config.html#example-languages). To add a language which is not supported by this package, you'll have to create your own view for how an example should render. Here's how: + For each endpoint, an example request is shown in each language configured. To add a language which is not supported by this package, you'll have to create your own view for how an example should render. Here's how: - Publish the vendor views by running: @@ -51,8 +54,8 @@ php artisan apidoc:rebuild - `methods`: an array of the HTTP methods for that route - `boundUri`: the complete URL for the route, with any url parameters replaced (/users/{id} -> /users/1) - `headers`: key-value array of headers to be sent with route (according to your configuration) -- `cleanQueryParameters`: key-value array of query parameters with example values to be sent with the request. Parameters which have been excluded from the example requests (see [Example Parameters](documenting.html#example-parameters)) will not be present here. -- `cleanBodyParameters`: key-value array of body parameters with example values to be sent with the request. Parameters which have been excluded from the example requests (see [Example Parameters](documenting.html#example-parameters)) will not be present here. +- `cleanQueryParameters`: key-value array of query parameters with example values to be sent with the request. Parameters which have been excluded from the example requests (see Example Parameters at Documenting your API) will not be present here. +- `cleanBodyParameters`: key-value array of body parameters with example values to be sent with the request. Parameters which have been excluded from the example requests (see Example Parameters at Documenting your API will not be present here. - Add the language to the `example_languages` array in the package config. diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md new file mode 100644 index 00000000..87c86b41 --- /dev/null +++ b/docs/getting-started/installation.md @@ -0,0 +1,35 @@ +--- +title: Installation +order: 1 +--- + +# Installation + +You can install Laravel API Documentation Generator using composer: + +```bash +composer require mpociot/laravel-apidoc-generator +``` + +## Laravel +Publish the config file by running: + +```bash +php artisan vendor:publish --provider="Mpociot\ApiDoc\ApiDocGeneratorServiceProvider" --tag=apidoc-config +``` +This will create an `apidoc.php` file in your `config` folder. + +## Lumen +Register the service provider in your `bootstrap/app.php`: + +```php +$app->register(\Mpociot\ApiDoc\ApiDocGeneratorServiceProvider::class); +``` + +Next, copy the config file from `vendor/mpociot/laravel-apidoc-generator/config/apidoc.php` to your project as `config/apidoc.php`. + +Then add to your `bootstrap/app.php`: + +```php +$app->configure('apidoc'); +``` \ No newline at end of file diff --git a/docs/migrating.md b/docs/getting-started/migrating.md similarity index 79% rename from docs/migrating.md rename to docs/getting-started/migrating.md index 7515615e..7112f39b 100644 --- a/docs/migrating.md +++ b/docs/getting-started/migrating.md @@ -1,3 +1,8 @@ +--- +title: Migrating from v3 to v4 +order: 10 +--- + # Migrating Note: This isn't meant to be an exhaustive guide to the changes in v4. Please see the changelog for more details (and full list of new features). @@ -10,9 +15,9 @@ Note: This isn't meant to be an exhaustive guide to the changes in v4. Please se - Remove the `output` key. Source files now go to `resources/docs/source` and generated docs go to either `public/docs/` or `resources/views/apidoc`. -- Make sure the `type` value is set appropriately. See [the docs](config.html#type). +- Make sure the `type` value is set appropriately. See [the docs](/docs/laravel-apidoc-generator/getting-started/configuration). -- Remove the `bindings` section. It has been superseded by the `@urlParam` annotation, which works similarly to the existing `@queryParam` annotation. See [the docs](documenting.html#specifying-request-parameters) +- Remove the `bindings` section. It has been superseded by the `@urlParam` annotation, which works similarly to the existing `@queryParam` annotation. See [the docs](/docs/laravel-apidoc-generator/getting-started/documenting-your-api) - Remove the `response_calls.bindings` section. Use the `Example: ` feature of `@urlParam` to specify the value you want to be used in response calls. @@ -27,9 +32,9 @@ The major change here is the introduction of the `urlParameters` section and the - The location of the source files for the generated docs has changed. Move any prepend/append files you've created from `public/docs/source` to the new location (`resources/docs/source`) ## API -- Verify that any custom strategies you've written match the new signatures. See [the docs](plugins.html#strategies). Also note the order of execution and the new stages present. +- Verify that any custom strategies you've written match the new signatures. See [the docs](/docs/laravel-apidoc-generator/extending/plugins). Also note the order of execution and the new stages present. ## Other new features (highlights) -- [Non-static docs/docs with authentication](config.html#type) -- [`@apiResource` for Eloquent API resources](documenting.html#apiresource-apiresourcecollection-and-apiresourcemodel) +- [Non-static docs/docs with authentication](/docs/laravel-apidoc-generator/getting-started/configuration) +- [`@apiResource` for Eloquent API resources](/docs/laravel-apidoc-generator/getting-started/documenting-your-api) - You can now mix and match response strategies and status codes as you like. diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 25c26d29..00000000 --- a/docs/index.md +++ /dev/null @@ -1,42 +0,0 @@ -# Overview - -Automatically generate your API documentation from your existing Laravel/Lumen/[Dingo](https://github.com/dingo/api) routes. [Here's what the output looks like](https://shalvah.me/TheCensorshipAPI/). - -`php artisan apidoc:generate` - -## Contents -* [How This Works](description.md) -* [Configuration](config.md) -* [Migrating from v3 to v4](migrating.md) -* [Generating Documentation](generating-documentation.md) -* [Documenting Your API](documenting.md) -* [Extending functionality with plugins](plugins.md) -* [Internal Architecture](architecture.md) - -## Installation -> Note: PHP 7 and Laravel 5.5 or higher are required. - -```sh -composer require mpociot/laravel-apidoc-generator -``` - -### Laravel -Publish the config file by running: - -```bash -php artisan vendor:publish --provider="Mpociot\ApiDoc\ApiDocGeneratorServiceProvider" --tag=apidoc-config -``` -This will create an `apidoc.php` file in your `config` folder. - -### Lumen -- Register the service provider in your `bootstrap/app.php`: - -```php -$app->register(\Mpociot\ApiDoc\ApiDocGeneratorServiceProvider::class); -``` - -- Copy the config file from `vendor/mpociot/laravel-apidoc-generator/config/apidoc.php` to your project as `config/apidoc.php`. Then add to your `bootstrap/app.php`: - -```php -$app->configure('apidoc'); -``` diff --git a/docs/under-the-hood/_index.md b/docs/under-the-hood/_index.md new file mode 100644 index 00000000..84027be5 --- /dev/null +++ b/docs/under-the-hood/_index.md @@ -0,0 +1,4 @@ +--- +title: Under the hood +order: 3 +--- diff --git a/docs/architecture.md b/docs/under-the-hood/architecture.md similarity index 96% rename from docs/architecture.md rename to docs/under-the-hood/architecture.md index aec01017..bb0f6d4f 100644 --- a/docs/architecture.md +++ b/docs/under-the-hood/architecture.md @@ -1,3 +1,7 @@ +--- +title: Architecture +order: 3 +--- # Architecture Read this page if you want a deeper understanding of how this works (for instance, for the purpose of contributing). diff --git a/docs/description.md b/docs/under-the-hood/how-it-works.md similarity index 68% rename from docs/description.md rename to docs/under-the-hood/how-it-works.md index 60297f5e..dc7e54b3 100644 --- a/docs/description.md +++ b/docs/under-the-hood/how-it-works.md @@ -1,9 +1,14 @@ +--- +title: How This Works +order: 2 +--- + # How This Works After installing this package and running the command `php artisan apidoc:generate` in your application, here's what happens: - The package fetches all your application's routes. -- It looks through your [configuration file](config.md) to filter the routes to the ones you actually want to document. For each route, it retrieves the settings you want to apply to it, if any. +- It looks through your configuration file to filter the routes to the ones you actually want to document. For each route, it retrieves the settings you want to apply to it, if any. - It processes each route. "Process" here involves using a number of strategies to extract the route's information: group, title, description, body parameters, query parameters, and a sample response, if possible. - After processing the routes, it generates a markdown file describing the routes from the parsed data and passes them to [Documentarian](https://github.com/mpociot/documentarian), which wraps them in a theme and converts them into HTML and CSS. -- It generates a Postman API collection for your routes. ([This can be disabled.](config.html#postman)) +- It generates a Postman API collection for your routes. This can be disabled. diff --git a/phpstan.neon b/phpstan.neon index bbbcf9b4..122c7957 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -11,3 +11,4 @@ parameters: - '#(.*)NunoMaduro\\Collision(.*)#' - '#Instantiated class Whoops\\Exception\\Inspector not found\.#' - '#.+Dingo.+#' + - '#Call to an undefined method Illuminate\\Contracts\\Filesystem\\Filesystem::url()#' diff --git a/src/Commands/GenerateDocumentation.php b/src/Commands/GenerateDocumentation.php index 95723bd6..783c7019 100644 --- a/src/Commands/GenerateDocumentation.php +++ b/src/Commands/GenerateDocumentation.php @@ -187,18 +187,20 @@ private function isRouteVisibleForDocumentation(array $routeControllerAndMethod) [$class, $method] = $routeControllerAndMethod; $reflection = new ReflectionClass($class); - $comment = $reflection->getMethod($method)->getDocComment(); - - if ($comment) { + $tags = collect(); + + foreach ( + array_filter([ + $reflection->getDocComment(), + $reflection->getMethod($method)->getDocComment() + ]) as $comment + ) { $phpdoc = new DocBlock($comment); - - return collect($phpdoc->getTags()) - ->filter(function ($tag) { - return $tag->getName() === 'hideFromAPIDocumentation'; - }) - ->isEmpty(); + $tags = $tags->concat($phpdoc->getTags()); } - return true; + return $tags->filter(function ($tag) { + return $tag->getName() === 'hideFromAPIDocumentation'; + })->isEmpty(); } } diff --git a/src/Extracting/Strategies/Metadata/GetFromDocBlocks.php b/src/Extracting/Strategies/Metadata/GetFromDocBlocks.php index 1c4c0b73..5edeec32 100644 --- a/src/Extracting/Strategies/Metadata/GetFromDocBlocks.php +++ b/src/Extracting/Strategies/Metadata/GetFromDocBlocks.php @@ -17,15 +17,16 @@ public function __invoke(Route $route, ReflectionClass $controller, ReflectionMe $docBlocks = RouteDocBlocker::getDocBlocksFromRoute($route); /** @var DocBlock $methodDocBlock */ $methodDocBlock = $docBlocks['method']; + $classDocBlock = $docBlocks['class']; - list($routeGroupName, $routeGroupDescription, $routeTitle) = $this->getRouteGroupDescriptionAndTitle($methodDocBlock, $docBlocks['class']); + list($routeGroupName, $routeGroupDescription, $routeTitle) = $this->getRouteGroupDescriptionAndTitle($methodDocBlock, $classDocBlock); return [ 'groupName' => $routeGroupName, 'groupDescription' => $routeGroupDescription, 'title' => $routeTitle ?: $methodDocBlock->getShortDescription(), 'description' => $methodDocBlock->getLongDescription()->getContents(), - 'authenticated' => $this->getAuthStatusFromDocBlock($methodDocBlock->getTags()), + 'authenticated' => $this->getAuthStatusFromDocBlock($classDocBlock->getTags()) ?: $this->getAuthStatusFromDocBlock($methodDocBlock->getTags()), ]; } @@ -48,7 +49,7 @@ protected function getAuthStatusFromDocBlock(array $tags) * @param DocBlock $methodDocBlock * @param DocBlock $controllerDocBlock * - * @return array The route group name, the group description, ad the route title + * @return array The route group name, the group description, and the route title */ protected function getRouteGroupDescriptionAndTitle(DocBlock $methodDocBlock, DocBlock $controllerDocBlock) { diff --git a/src/Extracting/Strategies/Strategy.php b/src/Extracting/Strategies/Strategy.php index d57d948b..19b7cc94 100644 --- a/src/Extracting/Strategies/Strategy.php +++ b/src/Extracting/Strategies/Strategy.php @@ -34,7 +34,7 @@ public function __construct(string $stage, DocumentationConfig $config) * * @throws \Exception * - * @return array + * @return array|null */ abstract public function __invoke(Route $route, ReflectionClass $controller, ReflectionMethod $method, array $routeRules, array $context = []); } diff --git a/src/Http/Controller.php b/src/Http/Controller.php index 2423c74a..b4c9a28c 100644 --- a/src/Http/Controller.php +++ b/src/Http/Controller.php @@ -19,7 +19,7 @@ public function html() public function json() { return response()->json( - json_decode(Storage::disk('local')->get('apidoc/collection.json')) + json_decode(Storage::disk(config('apidoc.storage'))->get('apidoc/collection.json')) ); } } diff --git a/src/Writing/Writer.php b/src/Writing/Writer.php index 63d7edfc..4c03f2f7 100644 --- a/src/Writing/Writer.php +++ b/src/Writing/Writer.php @@ -66,7 +66,7 @@ public function __construct(Command $output, DocumentationConfig $config = null, $this->documentarian = new Documentarian(); $this->isStatic = $this->config->get('type') === 'static'; $this->sourceOutputPath = 'resources/docs'; - $this->outputPath = $this->isStatic ? 'public/docs' : 'resources/views/apidoc'; + $this->outputPath = $this->isStatic ? ($this->config->get('output_folder') ?? 'public/docs') : 'resources/views/apidoc'; } public function writeDocs(Collection $routes) @@ -206,8 +206,13 @@ protected function writePostmanCollection(Collection $parsedRoutes): void $collectionPath = "{$this->outputPath}/collection.json"; file_put_contents($collectionPath, $collection); } else { - Storage::disk('local')->put('apidoc/collection.json', $collection); - $collectionPath = 'storage/app/apidoc/collection.json'; + $storageInstance = Storage::disk($this->config->get('storage')); + $storageInstance->put('apidoc/collection.json', $collection, 'public'); + if ($this->config->get('storage') == 'local') { + $collectionPath = 'storage/app/apidoc/collection.json'; + } else { + $collectionPath = $storageInstance->url('https://github.com/collection.json'); + } } $this->output->info("Wrote Postman collection to: {$collectionPath}"); @@ -252,7 +257,7 @@ protected function getMarkdownToAppend(): string protected function copyAssetsFromSourceFolderToPublicFolder(): void { - $publicPath = 'public/docs'; + $publicPath = $this->config->get('output_folder') ?? 'public/docs'; if (! is_dir($publicPath)) { mkdir($publicPath, 0777, true); mkdir("{$publicPath}/css"); @@ -280,8 +285,8 @@ protected function moveOutputFromSourceFolderToTargetFolder(): void rename("{$this->sourceOutputPath}/index.html", "$this->outputPath/index.blade.php"); $contents = file_get_contents("$this->outputPath/index.blade.php"); // - $contents = str_replace('href="https://github.com/css/style.css"', 'href="https://github.com/docs/css/style.css"', $contents); - $contents = str_replace('src="https://github.com/js/all.js"', 'src="https://github.com/docs/js/all.js"', $contents); + $contents = str_replace('href="https://github.com/css/style.css"', 'href="https://github.com/%7B%7B%20asset(/'/docs/css/style.css\') }}"', $contents); + $contents = str_replace('src="https://github.com/js/all.js"', 'src="https://github.com/%7B%7B%20asset(/'/docs/js/all.js\') }}"', $contents); $contents = str_replace('src="https://github.com/images/', 'src="https://github.com/docs/images/', $contents); $contents = preg_replace('#href="https://github.com/https?://.+?/docs/collection.json"#', 'href="https://github.com/%7B%7B%20route("apidoc.json") }}"', $contents); file_put_contents("$this->outputPath/index.blade.php", $contents);