mirror of
https://github.com/ambieco/scribe.git
synced 2026-04-23 21:31:21 +08:00
Allow translate rules descriptions.
This commit is contained in:
13
README.md
13
README.md
@@ -47,7 +47,18 @@ Option | Description
|
||||
`noResponseCalls` | Disable API response calls
|
||||
`actAsUserId` | The user ID to use for authenticated API response calls
|
||||
`router` | The router to use, when processing the route files (can be Laravel or Dingo - defaults to Laravel)
|
||||
`bindings` | List of route bindings that should be replaced when trying to retrieve route results. Syntax format: `binding_one,id|binding_two,id`
|
||||
`bindings` | List of route bindings that should be replaced when trying to retrieve route results. Syntax format: `binding_one,id|binding_two,id`
|
||||
|
||||
## Publish rule descriptions for customisation or translate.
|
||||
|
||||
For default, this package returns the descriptions in the main language of the application. But provides the possibility of publish the language files for customisation or translate.
|
||||
|
||||
```sh
|
||||
$ php artisan vendor:publish
|
||||
```
|
||||
|
||||
After to publish you can customize or translate the descriptions in the language you want by editing the files in `public/vendor/apidoc/resources/lang`.
|
||||
|
||||
|
||||
### How does it work?
|
||||
|
||||
|
||||
@@ -16,6 +16,11 @@ class ApiDocGeneratorServiceProvider extends ServiceProvider
|
||||
public function boot()
|
||||
{
|
||||
$this->loadViewsFrom(__DIR__.'/../../resources/views/', 'apidoc');
|
||||
$this->loadTranslationsFrom(__DIR__.'/../../resources/lang', 'apidoc');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__.'/../../resources/lang' => resource_path('lang/vendor/apidoc'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
namespace Mpociot\ApiDoc\Generators;
|
||||
|
||||
use Faker\Factory;
|
||||
use ReflectionClass;
|
||||
use Illuminate\Support\Str;
|
||||
use phpDocumentor\Reflection\DocBlock;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Mpociot\ApiDoc\Parsers\RuleDescriptionParser as Description;
|
||||
use ReflectionClass;
|
||||
use phpDocumentor\Reflection\DocBlock;
|
||||
|
||||
abstract class AbstractGenerator
|
||||
{
|
||||
@@ -196,102 +197,102 @@ abstract class AbstractGenerator
|
||||
break;
|
||||
case 'after':
|
||||
$attributeData['type'] = 'date';
|
||||
$attributeData['description'][] = 'Must be a date after: `'.date(DATE_RFC850, strtotime($parameters[0])).'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with(date(DATE_RFC850, strtotime($parameters[0])))->getDescription();
|
||||
$attributeData['value'] = date(DATE_RFC850, strtotime('+1 day', strtotime($parameters[0])));
|
||||
break;
|
||||
case 'alpha':
|
||||
$attributeData['description'][] = 'Only alphabetic characters allowed';
|
||||
$attributeData['description'][] = Description::parse($rule)->getDescription();
|
||||
$attributeData['value'] = $faker->word;
|
||||
break;
|
||||
case 'alpha_dash':
|
||||
$attributeData['description'][] = 'Allowed: alpha-numeric characters, as well as dashes and underscores.';
|
||||
$attributeData['description'][] = Description::parse($rule)->getDescription();
|
||||
break;
|
||||
case 'alpha_num':
|
||||
$attributeData['description'][] = 'Only alpha-numeric characters allowed';
|
||||
$attributeData['description'][] = Description::parse($rule)->getDescription();
|
||||
break;
|
||||
case 'in':
|
||||
$attributeData['description'][] = $this->fancyImplode($parameters, ', ', ' or ');
|
||||
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
|
||||
$attributeData['value'] = $faker->randomElement($parameters);
|
||||
break;
|
||||
case 'not_in':
|
||||
$attributeData['description'][] = 'Not in: '.$this->fancyImplode($parameters, ', ', ' or ');
|
||||
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
|
||||
$attributeData['value'] = $faker->word;
|
||||
break;
|
||||
case 'min':
|
||||
$attributeData['description'][] = 'Minimum: `'.$parameters[0].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
break;
|
||||
case 'max':
|
||||
$attributeData['description'][] = 'Maximum: `'.$parameters[0].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
break;
|
||||
case 'between':
|
||||
$attributeData['type'] = 'numeric';
|
||||
$attributeData['description'][] = 'Between: `'.$parameters[0].'` and `'.$parameters[1].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
$attributeData['value'] = $faker->numberBetween($parameters[0], $parameters[1]);
|
||||
break;
|
||||
case 'before':
|
||||
$attributeData['type'] = 'date';
|
||||
$attributeData['description'][] = 'Must be a date preceding: `'.date(DATE_RFC850, strtotime($parameters[0])).'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with(date(DATE_RFC850, strtotime($parameters[0])))->getDescription();
|
||||
$attributeData['value'] = date(DATE_RFC850, strtotime('-1 day', strtotime($parameters[0])));
|
||||
break;
|
||||
case 'date_format':
|
||||
$attributeData['type'] = 'date';
|
||||
$attributeData['description'][] = 'Date format: `'.$parameters[0].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
break;
|
||||
case 'different':
|
||||
$attributeData['description'][] = 'Must have a different value than parameter: `'.$parameters[0].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
break;
|
||||
case 'digits':
|
||||
$attributeData['type'] = 'numeric';
|
||||
$attributeData['description'][] = 'Must have an exact length of `'.$parameters[0].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
$attributeData['value'] = $faker->randomNumber($parameters[0], true);
|
||||
break;
|
||||
case 'digits_between':
|
||||
$attributeData['type'] = 'numeric';
|
||||
$attributeData['description'][] = 'Must have a length between `'.$parameters[0].'` and `'.$parameters[1].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
break;
|
||||
case 'image':
|
||||
$attributeData['type'] = 'image';
|
||||
$attributeData['description'][] = 'Must be an image (jpeg, png, bmp, gif, or svg)';
|
||||
$attributeData['description'][] = Description::parse($rule)->getDescription();
|
||||
break;
|
||||
case 'json':
|
||||
$attributeData['type'] = 'string';
|
||||
$attributeData['description'][] = 'Must be a valid JSON string.';
|
||||
$attributeData['description'][] = Description::parse($rule)->getDescription();
|
||||
$attributeData['value'] = json_encode(['foo', 'bar', 'baz']);
|
||||
break;
|
||||
case 'mimetypes':
|
||||
case 'mimes':
|
||||
$attributeData['description'][] = 'Allowed mime types: '.$this->fancyImplode($parameters, ', ', ' or ');
|
||||
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
|
||||
break;
|
||||
case 'required_if':
|
||||
$attributeData['description'][] = 'Required if `'.$parameters[0].'` is `'.$parameters[1].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
break;
|
||||
case 'required_unless':
|
||||
$attributeData['description'][] = 'Required unless `'.$parameters[0].'` is `'.$parameters[1].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
break;
|
||||
case 'required_with':
|
||||
$attributeData['description'][] = 'Required if the parameters '.$this->fancyImplode($parameters, ', ', ' or ').' are present.';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
|
||||
break;
|
||||
case 'required_with_all':
|
||||
$attributeData['description'][] = 'Required if the parameters '.$this->fancyImplode($parameters, ', ', ' and ').' are present.';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' and '))->getDescription();
|
||||
break;
|
||||
case 'required_without':
|
||||
$attributeData['description'][] = 'Required if the parameters '.$this->fancyImplode($parameters, ', ', ' or ').' are not present.';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
|
||||
break;
|
||||
case 'required_without_all':
|
||||
$attributeData['description'][] = 'Required if the parameters '.$this->fancyImplode($parameters, ', ', ' and ').' are not present.';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' and '))->getDescription();
|
||||
break;
|
||||
case 'same':
|
||||
$attributeData['description'][] = 'Must be the same as `'.$parameters[0].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
break;
|
||||
case 'size':
|
||||
$attributeData['description'][] = 'Must have the size of `'.$parameters[0].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
break;
|
||||
case 'timezone':
|
||||
$attributeData['description'][] = 'Must be a valid timezone identifier';
|
||||
$attributeData['description'][] = Description::parse($rule)->getDescription();
|
||||
$attributeData['value'] = $faker->timezone;
|
||||
break;
|
||||
case 'exists':
|
||||
$attributeData['description'][] = 'Valid '.Str::singular($parameters[0]).' '.$parameters[1];
|
||||
$attributeData['description'][] = Description::parse($rule)->with([Str::singular($parameters[0]), $parameters[1]])->getDescription();
|
||||
break;
|
||||
case 'active_url':
|
||||
$attributeData['type'] = 'url';
|
||||
@@ -299,7 +300,7 @@ abstract class AbstractGenerator
|
||||
break;
|
||||
case 'regex':
|
||||
$attributeData['type'] = 'string';
|
||||
$attributeData['description'][] = 'Must match this regular expression: `'.$parameters[0].'`';
|
||||
$attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
|
||||
break;
|
||||
case 'boolean':
|
||||
$attributeData['value'] = true;
|
||||
|
||||
75
src/Mpociot/ApiDoc/Parsers/RuleDescriptionParser.php
Normal file
75
src/Mpociot/ApiDoc/Parsers/RuleDescriptionParser.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Mpociot\ApiDoc\Parsers;
|
||||
|
||||
class RuleDescriptionParser
|
||||
{
|
||||
private $rule;
|
||||
|
||||
private $parameters = [];
|
||||
|
||||
/**
|
||||
* RuleDescriptionParser constructor.
|
||||
*
|
||||
* @param null $rule
|
||||
*/
|
||||
public function __construct($rule = null)
|
||||
{
|
||||
$this->rule = $rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description in the main language of the application.
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
$key = "apidoc::rules.{$this->rule}";
|
||||
|
||||
$description = $this->parameters ? $this->translateWithAttributes($key) : trans($key);
|
||||
|
||||
return $description != $key ? $description : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parameters for the description string.
|
||||
* @param string|array $parameters
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function with($parameters)
|
||||
{
|
||||
is_array($parameters) ? $this->parameters += $parameters : $this->parameters[] = $parameters;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description string with the replaced attributes.
|
||||
* @param $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function translateWithAttributes($key)
|
||||
{
|
||||
$translate = trans($key);
|
||||
|
||||
foreach ($this->parameters as $parameter) {
|
||||
$translate = preg_replace('/:attribute/', $parameter, $translate, 1);
|
||||
}
|
||||
|
||||
return $translate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a named constructor.
|
||||
* @param null $rule
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function parse($rule = null)
|
||||
{
|
||||
return new static($rule);
|
||||
}
|
||||
}
|
||||
33
src/resources/lang/en/rules.php
Normal file
33
src/resources/lang/en/rules.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'after' => 'Must be a date after: `:attribute`',
|
||||
'alpha' => 'Only alphabetic characters allowed',
|
||||
'alpha_dash' => 'Allowed: alpha-numeric characters, as well as dashes and underscores.',
|
||||
'alpha_num' => 'Only alpha-numeric characters allowed',
|
||||
'in' => ':attribute',
|
||||
'not_in' => 'Not in: :attribute',
|
||||
'min' => 'Minimum: `:attribute`',
|
||||
'max' => 'Maximum: `:attribute`',
|
||||
'between' => 'Between: `:attribute` and `:attribute`',
|
||||
'before' => 'Must be a date preceding: `:attribute`',
|
||||
'date_format' => 'Date format: `:attribute`',
|
||||
'different' => 'Must have a different value than parameter: `:attribute`',
|
||||
'digits' => 'Must have an exact length of `:attribute`',
|
||||
'digits_between' => 'Must have a length between `:attribute` and `:attribute`',
|
||||
'image' => 'Must be an image (jpeg, png, bmp, gif, or svg)',
|
||||
'json' => 'Must be a valid JSON string.',
|
||||
'mimetypes' => 'Allowed mime types: :attribute',
|
||||
'mimes' => 'Allowed mime types: :attribute',
|
||||
'required_if' => 'Required if `:attribute` is `:attribute`',
|
||||
'required_unless' => 'Required unless `:attribute` is `:attribute`',
|
||||
'required_with' => 'Required if the parameters :attribute are present.',
|
||||
'required_with_all' => 'Required if the parameters :attribute are present.',
|
||||
'required_without' => 'Required if the parameters :attribute are not present.',
|
||||
'required_without_all' => 'Required if the parameters :attribute are not present.',
|
||||
'same' => 'Must be the same as `:attribute`',
|
||||
'size' => 'Must have the size of `:attribute`',
|
||||
'timezone' => 'Must be a valid timezone identifier',
|
||||
'exists' => 'Valid :attribute :attribute',
|
||||
'regex' => 'Must match this regular expression: `:attribute`',
|
||||
];
|
||||
@@ -3,11 +3,12 @@
|
||||
namespace Mpociot\ApiDoc\Tests;
|
||||
|
||||
use Illuminate\Routing\Route;
|
||||
use Mpociot\ApiDoc\Generators\LaravelGenerator;
|
||||
use Orchestra\Testbench\TestCase;
|
||||
use Mpociot\ApiDoc\Tests\Fixtures\TestRequest;
|
||||
use Mpociot\ApiDoc\Tests\Fixtures\TestController;
|
||||
use Illuminate\Support\Facades\Route as RouteFacade;
|
||||
use Mpociot\ApiDoc\ApiDocGeneratorServiceProvider;
|
||||
use Mpociot\ApiDoc\Generators\LaravelGenerator;
|
||||
use Mpociot\ApiDoc\Tests\Fixtures\TestController;
|
||||
use Mpociot\ApiDoc\Tests\Fixtures\TestRequest;
|
||||
use Orchestra\Testbench\TestCase;
|
||||
|
||||
class ApiDocGeneratorTest extends TestCase
|
||||
{
|
||||
@@ -16,6 +17,13 @@ class ApiDocGeneratorTest extends TestCase
|
||||
*/
|
||||
protected $generator;
|
||||
|
||||
protected function getPackageProviders($app)
|
||||
{
|
||||
return [
|
||||
ApiDocGeneratorServiceProvider::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the test environment.
|
||||
*/
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
namespace Mpociot\ApiDoc\Tests;
|
||||
|
||||
use Dingo\Api\Provider\LaravelServiceProvider;
|
||||
use Mpociot\ApiDoc\Tests\Fixtures\DingoTestController;
|
||||
use Orchestra\Testbench\TestCase;
|
||||
use Mpociot\ApiDoc\ApiDocGeneratorServiceProvider;
|
||||
use Mpociot\ApiDoc\Generators\DingoGenerator;
|
||||
use Mpociot\ApiDoc\Tests\Fixtures\TestRequest;
|
||||
use Mpociot\ApiDoc\Tests\Fixtures\DingoTestController;
|
||||
use Mpociot\ApiDoc\Tests\Fixtures\TestController;
|
||||
use Mpociot\ApiDoc\Tests\Fixtures\TestRequest;
|
||||
use Orchestra\Testbench\TestCase;
|
||||
|
||||
class DingoGeneratorTest extends TestCase
|
||||
{
|
||||
@@ -20,6 +21,7 @@ class DingoGeneratorTest extends TestCase
|
||||
{
|
||||
return [
|
||||
LaravelServiceProvider::class,
|
||||
ApiDocGeneratorServiceProvider::class,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
90
tests/RuleDescriptionParserTest.php
Normal file
90
tests/RuleDescriptionParserTest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Mpociot\ApiDoc\Tests;
|
||||
|
||||
use Mpociot\ApiDoc\ApiDocGeneratorServiceProvider;
|
||||
use Mpociot\ApiDoc\Parsers\RuleDescriptionParser;
|
||||
use Orchestra\Testbench\TestCase;
|
||||
|
||||
class RuleDescriptionParserTest extends TestCase
|
||||
{
|
||||
public function testReturnsAnEmptyDescriptionIfARuleIsNotParsed()
|
||||
{
|
||||
$rule = new RuleDescriptionParser();
|
||||
|
||||
$this->assertEmpty($rule->getDescription());
|
||||
}
|
||||
|
||||
public function testProvidesANamedContructor()
|
||||
{
|
||||
$this->assertInstanceOf(RuleDescriptionParser::class, RuleDescriptionParser::parse());
|
||||
}
|
||||
|
||||
public function testReturnsADescriptionInTheMainLanguageOfTheApplication()
|
||||
{
|
||||
$expected = 'Only alphabetic characters allowed';
|
||||
$rule = new RuleDescriptionParser('alpha');
|
||||
|
||||
$this->assertEquals($expected, $rule->getDescription());
|
||||
}
|
||||
|
||||
public function testReturnsAnEmptyDescriptionIfNotAvailable()
|
||||
{
|
||||
$rule = new RuleDescriptionParser('dummy_rule');
|
||||
|
||||
$description = $rule->getDescription();
|
||||
|
||||
$this->assertEmpty($description);
|
||||
}
|
||||
|
||||
public function testAllowsToPassParametersToTheDescription()
|
||||
{
|
||||
$expected = 'Must have an exact length of `2`';
|
||||
$rule = new RuleDescriptionParser('digits');
|
||||
|
||||
$actual = $rule->with(2)->getDescription();
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testOnlyPassesParametersIfTheDescriptionAllows()
|
||||
{
|
||||
$expected = 'Only alphabetic characters allowed';
|
||||
$rule = new RuleDescriptionParser('alpha');
|
||||
|
||||
$actual = $rule->with("dummy parameter")->getDescription();
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
public function testAllowsToPassMultipleParametersToTheDescription()
|
||||
{
|
||||
$expected = 'Required if `2 + 2` is `4`';
|
||||
$rule = new RuleDescriptionParser('required_if');
|
||||
|
||||
$actual = $rule->with(['2 + 2', 4])->getDescription();
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getPackageProviders($app)
|
||||
{
|
||||
return [ApiDocGeneratorServiceProvider::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* Define environment setup.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
* @return void
|
||||
*/
|
||||
protected function getEnvironmentSetUp($app)
|
||||
{
|
||||
$app['config']->set('app.locale', 'en');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user