API Docs: Allowed multi-paragraph descriptions
Added support for mulit-line endpoint descriptions via blank intermediate lines in php controller method docblocks. Also tweaks endpoint header design for better flexing and alignment.
This commit is contained in:
		
							parent
							
								
									4bb2cf5c5f
								
							
						
					
					
						commit
						38883e8d46
					
				| 
						 | 
					@ -16,8 +16,8 @@ use ReflectionMethod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ApiDocsGenerator
 | 
					class ApiDocsGenerator
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    protected $reflectionClasses = [];
 | 
					    protected array $reflectionClasses = [];
 | 
				
			||||||
    protected $controllerClasses = [];
 | 
					    protected array $controllerClasses = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Load the docs form the cache if existing
 | 
					     * Load the docs form the cache if existing
 | 
				
			||||||
| 
						 | 
					@ -139,9 +139,10 @@ class ApiDocsGenerator
 | 
				
			||||||
    protected function parseDescriptionFromMethodComment(string $comment): string
 | 
					    protected function parseDescriptionFromMethodComment(string $comment): string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $matches = [];
 | 
					        $matches = [];
 | 
				
			||||||
        preg_match_all('/^\s*?\*\s((?![@\s]).*?)$/m', $comment, $matches);
 | 
					        preg_match_all('/^\s*?\*\s?($|((?![\/@\s]).*?))$/m', $comment, $matches);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return implode(' ', $matches[1] ?? []);
 | 
					        $text = implode(' ', $matches[1] ?? []);
 | 
				
			||||||
 | 
					        return str_replace('  ', "\n", $text);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,6 @@ class PageApiController extends ApiController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * View the details of a single page.
 | 
					     * View the details of a single page.
 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * Pages will always have HTML content. They may have markdown content
 | 
					     * Pages will always have HTML content. They may have markdown content
 | 
				
			||||||
     * if the markdown editor was used to last update the page.
 | 
					     * if the markdown editor was used to last update the page.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,8 +38,10 @@ class ContentPermissionApiController extends ApiController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Read the configured content-level permissions for the item of the given type and ID.
 | 
					     * Read the configured content-level permissions for the item of the given type and ID.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
     * 'contentType' should be one of: page, book, chapter, bookshelf.
 | 
					     * 'contentType' should be one of: page, book, chapter, bookshelf.
 | 
				
			||||||
     * 'contentId' should be the relevant ID of that item type you'd like to handle permissions for.
 | 
					     * 'contentId' should be the relevant ID of that item type you'd like to handle permissions for.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
     * The permissions shown are those that override the default for just the specified item, they do not show the
 | 
					     * The permissions shown are those that override the default for just the specified item, they do not show the
 | 
				
			||||||
     * full evaluated permission for a role, nor do they reflect permissions inherited from other items in the hierarchy.
 | 
					     * full evaluated permission for a role, nor do they reflect permissions inherited from other items in the hierarchy.
 | 
				
			||||||
     * Fallback permission values may be `null` when inheriting is active.
 | 
					     * Fallback permission values may be `null` when inheriting is active.
 | 
				
			||||||
| 
						 | 
					@ -57,6 +59,7 @@ class ContentPermissionApiController extends ApiController
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Update the configured content-level permission overrides for the item of the given type and ID.
 | 
					     * Update the configured content-level permission overrides for the item of the given type and ID.
 | 
				
			||||||
     * 'contentType' should be one of: page, book, chapter, bookshelf.
 | 
					     * 'contentType' should be one of: page, book, chapter, bookshelf.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
     * 'contentId' should be the relevant ID of that item type you'd like to handle permissions for.
 | 
					     * 'contentId' should be the relevant ID of that item type you'd like to handle permissions for.
 | 
				
			||||||
     * Providing an empty `role_permissions` array will remove any existing configured role permissions,
 | 
					     * Providing an empty `role_permissions` array will remove any existing configured role permissions,
 | 
				
			||||||
     * so you may want to fetch existing permissions beforehand if just adding/removing a single item.
 | 
					     * so you may want to fetch existing permissions beforehand if just adding/removing a single item.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,8 +52,10 @@ class ImageGalleryApiController extends ApiController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Create a new image in the system.
 | 
					     * Create a new image in the system.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
     * Since "image" is expected to be a file, this needs to be a 'multipart/form-data' type request.
 | 
					     * Since "image" is expected to be a file, this needs to be a 'multipart/form-data' type request.
 | 
				
			||||||
     * The provided "uploaded_to" should be an existing page ID in the system.
 | 
					     * The provided "uploaded_to" should be an existing page ID in the system.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
     * If the "name" parameter is omitted, the filename of the provided image file will be used instead.
 | 
					     * If the "name" parameter is omitted, the filename of the provided image file will be used instead.
 | 
				
			||||||
     * The "type" parameter should be 'gallery' for page content images, and 'drawio' should only be used
 | 
					     * The "type" parameter should be 'gallery' for page content images, and 'drawio' should only be used
 | 
				
			||||||
     * when the file is a PNG file with diagrams.net image data embedded within.
 | 
					     * when the file is a PNG file with diagrams.net image data embedded within.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,20 @@
 | 
				
			||||||
<h6 class="text-uppercase text-muted float right">{{ $endpoint['controller_method_kebab'] }}</h6>
 | 
					<div class="flex-container-row items-center gap-m">
 | 
				
			||||||
 | 
					    <span class="api-method text-mono" data-method="{{ $endpoint['method'] }}">{{ $endpoint['method'] }}</span>
 | 
				
			||||||
 | 
					    <h5 id="{{ $endpoint['name'] }}" class="text-mono pb-xs">
 | 
				
			||||||
 | 
					        @if($endpoint['controller_method_kebab'] === 'list')
 | 
				
			||||||
 | 
					            <a style="color: inherit;" target="_blank" rel="noopener" href="{{ url($endpoint['uri']) }}">{{ url($endpoint['uri']) }}</a>
 | 
				
			||||||
 | 
					        @else
 | 
				
			||||||
 | 
					            <span>{{ url($endpoint['uri']) }}</span>
 | 
				
			||||||
 | 
					        @endif
 | 
				
			||||||
 | 
					    </h5>
 | 
				
			||||||
 | 
					    <h6 class="text-uppercase text-muted text-mono ml-auto">{{ $endpoint['controller_method_kebab'] }}</h6>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<h5 id="{{ $endpoint['name'] }}" class="text-mono mb-m">
 | 
					<div class="mb-m">
 | 
				
			||||||
    <span class="api-method" data-method="{{ $endpoint['method'] }}">{{ $endpoint['method'] }}</span>
 | 
					    @foreach(explode("\n", $endpoint['description'] ?? '') as $descriptionBlock)
 | 
				
			||||||
    @if($endpoint['controller_method_kebab'] === 'list')
 | 
					        <p class="mb-xxs">{{ $descriptionBlock }}</p>
 | 
				
			||||||
        <a style="color: inherit;" target="_blank" rel="noopener" href="{{ url($endpoint['uri']) }}">{{ url($endpoint['uri']) }}</a>
 | 
					    @endforeach
 | 
				
			||||||
    @else
 | 
					</div>
 | 
				
			||||||
        {{ url($endpoint['uri']) }}
 | 
					 | 
				
			||||||
    @endif
 | 
					 | 
				
			||||||
</h5>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<p class="mb-m">{{ $endpoint['description'] ?? '' }}</p>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@if($endpoint['body_params'] ?? false)
 | 
					@if($endpoint['body_params'] ?? false)
 | 
				
			||||||
    <details class="mb-m">
 | 
					    <details class="mb-m">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ class ApiDocsTest extends TestCase
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    use TestsApi;
 | 
					    use TestsApi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected $endpoint = '/api/docs';
 | 
					    protected string $endpoint = '/api/docs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function test_api_endpoint_redirects_to_docs()
 | 
					    public function test_api_endpoint_redirects_to_docs()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue