sp-api-sdk
sp-api-sdk copied to clipboard
Request's body not validated
Currently the ObjectSerializer checks the type of data.
if Value is null, it won't throw any error that's where the function validate should throw an error, but it is never called. Example: this block should validate data of type array, it does not check if the array is empty
class \AmazonPHP\SellingPartner\ObjectSerializer::sanitizeForSerialization
if (\is_array($data)) {
foreach ($data as $property => $value) {
$data[$property] = self::sanitizeForSerialization($value);
}
return $data;
}
The validation should take place in function validate()
class: \AmazonPHP\SellingPartner\Model\ListingsItems\FulfillmentAvailability::validate
/**
* Validate all properties.
*
* @throws AssertionException
*/
public function validate() : void
{
if ($this->container['fulfillment_channel_code'] === null) {
throw new AssertionException("'fulfillment_channel_code' can't be null");
}
if (null !== $this->container['quantity'] && ($this->container['quantity'] < 0)) {
throw new AssertionException("invalid value for 'quantity', must be bigger than or equal to 0.");
}
}
Solution: we should add $data->validate; inside if ($data instanceof ModelInterface)
/**
* Serialize data.
*
* @param mixed $data the data to serialize
* @param null|string $type the OpenAPIToolsType of the data
* @param null|string $format the format of the OpenAPITools type of the data
*
* @return null|array|object|scalar serialized form of $data
*/
public static function sanitizeForSerialization(mixed $data, string $type = null, string $format = null)
{
if (\is_scalar($data) || null === $data) {
return $data;
}
if ($data instanceof \DateTimeInterface) {
return ($format === 'date') ? $data->format('Y-m-d') : $data->setTimezone(new \DateTimeZone('UTC'))->format(self::$dateTimeFormat);
}
if (\is_array($data)) {
foreach ($data as $property => $value) {
$data[$property] = self::sanitizeForSerialization($value);
}
return $data;
}
if (\is_object($data)) {
$values = [];
if ($data instanceof ModelInterface) {
$formats = $data::openAPIFormats();
foreach ($data::openAPITypes() as $property => $openAPIType) {
$getter = $data::getters()[$property];
$value = $data->{$getter}();
if ($value !== null && \is_object($value) && \method_exists($value, 'getAllowableEnumValues')) {
$callable = [$openAPIType, 'getAllowableEnumValues'];
if (\is_callable($callable)) {
/** array $callable */
$allowedEnumTypes = $callable();
if (!\in_array($value->toString(), $allowedEnumTypes, true) &&
!\in_array(\ltrim((string) $openAPIType, '\\'), self::getBrokenModelDefinitions(), true)) {
$imploded = \implode("', '", $allowedEnumTypes);
throw new \InvalidArgumentException("Invalid value for enum '{$openAPIType}', must be one of: '{$imploded}'");
}
}
$value = $value->toString();
}
if ($value !== null) {
$values[$data::attributeMap()[$property]] = self::sanitizeForSerialization($value, $openAPIType, $formats[$property]);
}
}
} else {
foreach ($data as $property => $value) {
$values[$property] = self::sanitizeForSerialization($value);
}
}
return $values;
}
return (string) $data;
}