|
@@ -50,7 +50,7 @@ class GetFromFormRequest extends Strategy
|
|
|
$parameterClass = new ReflectionClass($parameterClassName);
|
|
|
} catch (ReflectionException $e) {
|
|
|
|
|
|
- dump($e->getMessage());
|
|
|
+ dump("Exception: " . $e->getMessage());
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -65,7 +65,7 @@ class GetFromFormRequest extends Strategy
|
|
|
$this->getCustomParameterData($formRequest)
|
|
|
);
|
|
|
|
|
|
- return $bodyParametersFromFormRequest;
|
|
|
+ return $this->normaliseArrayAndObjectParameters($bodyParametersFromFormRequest);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -159,6 +159,7 @@ class GetFromFormRequest extends Strategy
|
|
|
$parameterData['value'] = $this->castToType($parameterData['value'], $parameterData['type']);
|
|
|
}
|
|
|
|
|
|
+ $parameterData['name'] = $parameter;
|
|
|
$parameters[$parameter] = $parameterData;
|
|
|
}
|
|
|
|
|
@@ -179,26 +180,17 @@ class GetFromFormRequest extends Strategy
|
|
|
// but Laravel will ignore any nested array rules (`ids.*')
|
|
|
// unless the key referenced (`ids`) exists in the dataset and is a non-empty array
|
|
|
// So we'll create a single-item array for each array parameter
|
|
|
- $values = collect($rules)
|
|
|
- ->filter(function ($value, $key) {
|
|
|
- return Str::contains($key, '.*');
|
|
|
- })->mapWithKeys(function ($value, $key) {
|
|
|
- if (Str::endsWith($key, '.*')) {
|
|
|
- // We're dealing with a simple array of primitives
|
|
|
- return [Str::substr($key, 0, -2) => [Str::random()]];
|
|
|
- } elseif (Str::contains($key, '.*.')) {
|
|
|
- // We're dealing with an array of objects
|
|
|
- [$key, $property] = explode('.*.', $key);
|
|
|
-
|
|
|
- // Even though this will be overwritten by another property declaration in the rules, we're fine.
|
|
|
- // All we need is for Laravel to see this key exists
|
|
|
- return [$key => [[$property => Str::random()]]];
|
|
|
- }
|
|
|
- })->all();
|
|
|
+ $testData = [];
|
|
|
+ foreach ($rules as $key => $ruleset) {
|
|
|
+ if (!Str::contains($key, '.*')) continue;
|
|
|
+
|
|
|
+ // All we need is for Laravel to see this key exists
|
|
|
+ Arr::set($testData, str_replace('.*', '.0', $key), Str::random());
|
|
|
+ }
|
|
|
|
|
|
// Now this will return the complete ruleset.
|
|
|
// Nested array parameters will be present, with '*' replaced by '0'
|
|
|
- $newRules = Validator::make($values, $rules)->getRules();
|
|
|
+ $newRules = Validator::make($testData, $rules)->getRules();
|
|
|
|
|
|
// Transform the key names back from 'ids.0' to 'ids.*'
|
|
|
return collect($newRules)->mapWithKeys(function ($val, $paramName) use ($rules) {
|
|
@@ -413,5 +405,89 @@ class GetFromFormRequest extends Strategy
|
|
|
|
|
|
return [strtolower(trim($rule)), $ruleArguments];
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Laravel uses .* notation for arrays. This PR aims to normalise that into our "new syntax".
|
|
|
+ *
|
|
|
+ * 'years.*' with type 'integer' becomes 'years' with type 'integer[]'
|
|
|
+ * 'cars.*.age' with type 'string' becomes 'cars[].age' with type 'string' and 'cars' with type 'object[]'
|
|
|
+ * 'cars.*.things.*.*' with type 'string' becomes 'cars[].things' with type 'string[][]' and 'cars' with type
|
|
|
+ * 'object[]'
|
|
|
+ *
|
|
|
+ * @param <string, array>[] $bodyParametersFromValidationRules
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public function normaliseArrayAndObjectParameters(array $bodyParametersFromValidationRules): array
|
|
|
+ {
|
|
|
+ $results = [];
|
|
|
+ foreach ($bodyParametersFromValidationRules as $name => $details) {
|
|
|
+ // Change cars.*.dogs.things.*.* with type X to cars.*.dogs.things with type X[][]
|
|
|
+ while (Str::endsWith($name, '.*')) {
|
|
|
+ $details['type'] .= '[]';
|
|
|
+ $name = substr($name, 0, -2);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Now make sure the field cars.*.dogs exists
|
|
|
+ $parentPath = $name;
|
|
|
+ while (Str::contains($parentPath, '.')) {
|
|
|
+ $parentPath = preg_replace('/\.[^.]+$/', '', $parentPath);
|
|
|
+ if (empty($bodyParametersFromValidationRules[$parentPath])) {
|
|
|
+ if (Str::endsWith($parentPath, '.*')) {
|
|
|
+ $parentPath = substr($parentPath, 0, -2);
|
|
|
+ $type = 'object[]';
|
|
|
+ $value = [[]];
|
|
|
+ } else {
|
|
|
+ $type = 'object';
|
|
|
+ $value = [];
|
|
|
+ }
|
|
|
+ $normalisedPath = str_replace('.*.', '[].', $parentPath);
|
|
|
+ $results[$normalisedPath] = [
|
|
|
+ 'name' => $normalisedPath,
|
|
|
+ 'type' => $type,
|
|
|
+ 'required' => false,
|
|
|
+ 'description' => '',
|
|
|
+ 'value' => $value,
|
|
|
+ ];
|
|
|
+ } else {
|
|
|
+ // if the parent field already exists with a type 'array'
|
|
|
+ $parentDetails = $bodyParametersFromValidationRules[$parentPath];
|
|
|
+ unset($bodyParametersFromValidationRules[$parentPath]);
|
|
|
+ if (Str::endsWith($parentPath, '.*')) {
|
|
|
+ $parentPath = substr($parentPath, 0, -2);
|
|
|
+ $parentDetails['type'] = 'object[]';
|
|
|
+ // Set the example too. Very likely the example array was an array of strings or an empty array
|
|
|
+ if (empty($parentDetails['value']) || is_string($parentDetails['value'][0]) || is_string($parentDetails['value'][0][0])) {
|
|
|
+ $parentDetails['value'] = [[]];
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $parentDetails['type'] = 'object';
|
|
|
+ if (empty($parentDetails['value']) || is_string($parentDetails['value'][0])) {
|
|
|
+ $parentDetails['value'] = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $normalisedPath = str_replace('.*.', '[].', $parentPath);
|
|
|
+ $parentDetails['name'] = $normalisedPath;
|
|
|
+ $results[$normalisedPath] = $parentDetails;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $details['name'] = $name = str_replace('.*.', '[].', $name);
|
|
|
+ unset($details['setter']);
|
|
|
+
|
|
|
+ // Change type 'array' to 'object' if there are subfields
|
|
|
+ if (
|
|
|
+ $details['type'] === 'array'
|
|
|
+ && Arr::first(array_keys($bodyParametersFromValidationRules), function ($key) use ($name) {
|
|
|
+ return preg_match("/{$name}\\.[^*]/", $key);
|
|
|
+ })
|
|
|
+ ) {
|
|
|
+ $details['type'] = 'object';
|
|
|
+ }
|
|
|
+ $results[$name] = $details;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $results;
|
|
|
+ }
|
|
|
}
|
|
|
|