ParamHelpers.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. namespace Mpociot\ApiDoc\Tools\Traits;
  3. use Faker\Factory;
  4. use Illuminate\Support\Arr;
  5. use Illuminate\Support\Str;
  6. use Mpociot\Reflection\DocBlock\Tag;
  7. trait ParamHelpers
  8. {
  9. /**
  10. * Create proper arrays from dot-noted parameter names. Also filter out parameters which were excluded from having examples.
  11. *
  12. * @param array $params
  13. *
  14. * @return array
  15. */
  16. protected function cleanParams(array $params)
  17. {
  18. $values = [];
  19. $params = array_filter($params, function ($details) {
  20. return ! is_null($details['value']);
  21. });
  22. foreach ($params as $name => $details) {
  23. $this->cleanValueFrom($name, $details['value'], $values);
  24. }
  25. return $values;
  26. }
  27. /**
  28. * Converts dot notation names to arrays and sets the value at the right depth.
  29. *
  30. * @param string $name
  31. * @param mixed $value
  32. * @param array $values The array that holds the result
  33. *
  34. * @return void
  35. */
  36. protected function cleanValueFrom($name, $value, array &$values = [])
  37. {
  38. if (Str::contains($name, '[')) {
  39. $name = str_replace(['][', '[', ']', '..'], ['.', '.', '', '.*.'], $name);
  40. }
  41. Arr::set($values, str_replace('.*', '.0', $name), $value);
  42. }
  43. /**
  44. * Allows users to specify that we shouldn't generate an example for the parameter
  45. * by writing 'No-example'.
  46. *
  47. * @param Tag $tag
  48. *
  49. * @return bool Whether no example should be generated
  50. */
  51. private function shouldExcludeExample(Tag $tag)
  52. {
  53. return strpos($tag->getContent(), ' No-example') !== false;
  54. }
  55. private function generateDummyValue(string $type)
  56. {
  57. $faker = Factory::create();
  58. if ($this->config->get('faker_seed')) {
  59. $faker->seed($this->config->get('faker_seed'));
  60. }
  61. $fakeFactories = [
  62. 'integer' => function () use ($faker) {
  63. return $faker->numberBetween(1, 20);
  64. },
  65. 'number' => function () use ($faker) {
  66. return $faker->randomFloat();
  67. },
  68. 'float' => function () use ($faker) {
  69. return $faker->randomFloat();
  70. },
  71. 'boolean' => function () use ($faker) {
  72. return $faker->boolean();
  73. },
  74. 'string' => function () use ($faker) {
  75. return $faker->word;
  76. },
  77. 'array' => function () {
  78. return [];
  79. },
  80. 'object' => function () {
  81. return new \stdClass;
  82. },
  83. ];
  84. $fakeFactory = $fakeFactories[$type] ?? $fakeFactories['string'];
  85. return $fakeFactory();
  86. }
  87. /**
  88. * Allows users to specify an example for the parameter by writing 'Example: the-example',
  89. * to be used in example requests and response calls.
  90. *
  91. * @param string $description
  92. * @param string $type The type of the parameter. Used to cast the example provided, if any.
  93. *
  94. * @return array The description and included example.
  95. */
  96. private function parseParamDescription(string $description, string $type)
  97. {
  98. $example = null;
  99. if (preg_match('/(.*)\s+Example:\s*(.*)\s*/', $description, $content)) {
  100. $description = $content[1];
  101. // examples are parsed as strings by default, we need to cast them properly
  102. $example = $this->castToType($content[2], $type);
  103. }
  104. return [$description, $example];
  105. }
  106. /**
  107. * Cast a value from a string to a specified type.
  108. *
  109. * @param string $value
  110. * @param string $type
  111. *
  112. * @return mixed
  113. */
  114. private function castToType(string $value, string $type)
  115. {
  116. $casts = [
  117. 'integer' => 'intval',
  118. 'number' => 'floatval',
  119. 'float' => 'floatval',
  120. 'boolean' => 'boolval',
  121. ];
  122. // First, we handle booleans. We can't use a regular cast,
  123. //because PHP considers string 'false' as true.
  124. if ($value == 'false' && $type == 'boolean') {
  125. return false;
  126. }
  127. if (isset($casts[$type])) {
  128. return $casts[$type]($value);
  129. }
  130. return $value;
  131. }
  132. private function normalizeParameterType(string $type)
  133. {
  134. $typeMap = [
  135. 'int' => 'integer',
  136. 'bool' => 'boolean',
  137. 'double' => 'float',
  138. ];
  139. return $type ? ($typeMap[$type] ?? $type) : 'string';
  140. }
  141. }