Skip to content

Update for compatibility with symfony/serializer 7 #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed

Update for compatibility with symfony/serializer 7 #46

wants to merge 2 commits into from

Conversation

theteknocat
Copy link

Updated the function signatures of normalize and denormalize to match those defined by the interfaces being called for. Also updated the denormalize method to use an updated argument name.

Resolves #45.

@theteknocat theteknocat changed the title Update for compatibility with Symfony updates Update for compatibility with symfony/serializer 7 Feb 10, 2024
@finwe
Copy link

finwe commented Mar 19, 2024

I just ran into the same incompatibility and thanks for the effort, just my two cents: shouldn't this update also include updating/setting up the used jane-php/open-api-runtime utility and the code regenerated by it, instead of seemingly updating the files somewhat manually?

@xavierlacot
Copy link
Member

Hi @theteknocat and @finwe

Thank you for bringing this issue to my attention! Sorry I overlooked it.

As finwe explained, instead of just updating the content in the generated folder, we should rather update jane and its configuration, and then use the jane tolling to let it generate the code that sites in generated.

More generally, update/upgrade tasks for this library are divided into two parts:

  • the update the openapi specification, in case of endpoint changes: the original OpenAPI file comes from the jolicode/harvest-openapi-generator respository - it is a tool that parses the HTML docs to generate a valide OpenAPI specification
  • the update of the Harvest PHP API SDK. To achieve this, we rely entirely on Jane to manage the compatibility with the projects's environment. For example, recent versions of Jane add a compatibility layer, so generated libs are compatibile with old and recent versions of the serializer.

I am going to open a separate pull request that does both of this changes, and I'll let you test if this works for your case?

Thanks a lot again for your interest in this library 🙂

@xavierlacot
Copy link
Member

So here it is: #47

By upgrading Jane and letting it re-generate the SDK, it has automatically added a compat layer, so this new version will work in environments with recent or older versions of the serializer.

See for example the class BillableRatesNormalizer:

if (!class_exists(Kernel::class) || (Kernel::MAJOR_VERSION >= 7 || Kernel::MAJOR_VERSION === 6 && Kernel::MINOR_VERSION === 4)) {
class BillableRatesNormalizer implements DenormalizerInterface, NormalizerInterface, DenormalizerAwareInterface, NormalizerAwareInterface
{
use CheckArray;
use DenormalizerAwareTrait;
use NormalizerAwareTrait;
use ValidatorTrait;
public function supportsDenormalization(mixed $data, string $type, ?string $format = null, array $context = []): bool
{
return 'JoliCode\\Harvest\\Api\\Model\\BillableRates' === $type;
}
public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
{
return \is_object($data) && 'JoliCode\\Harvest\\Api\\Model\\BillableRates' === $data::class;
}
public function denormalize(mixed $data, string $type, ?string $format = null, array $context = []): mixed
{
if (isset($data['$ref'])) {
return new Reference($data['$ref'], $context['document-origin']);
}
if (isset($data['$recursiveRef'])) {
return new Reference($data['$recursiveRef'], $context['document-origin']);
}
$object = new \JoliCode\Harvest\Api\Model\BillableRates();
if (null === $data || false === \is_array($data)) {
return $object;
}
if (\array_key_exists('billable_rates', $data)) {
$values = [];
foreach ($data['billable_rates'] as $value) {
$values[] = $this->denormalizer->denormalize($value, 'JoliCode\\Harvest\\Api\\Model\\BillableRate', 'json', $context);
}
$object->setBillableRates($values);
unset($data['billable_rates']);
}
if (\array_key_exists('per_page', $data)) {
$object->setPerPage($data['per_page']);
unset($data['per_page']);
}
if (\array_key_exists('total_pages', $data)) {
$object->setTotalPages($data['total_pages']);
unset($data['total_pages']);
}
if (\array_key_exists('total_entries', $data)) {
$object->setTotalEntries($data['total_entries']);
unset($data['total_entries']);
}
if (\array_key_exists('next_page', $data) && null !== $data['next_page']) {
$object->setNextPage($data['next_page']);
unset($data['next_page']);
} elseif (\array_key_exists('next_page', $data) && null === $data['next_page']) {
$object->setNextPage(null);
}
if (\array_key_exists('previous_page', $data) && null !== $data['previous_page']) {
$object->setPreviousPage($data['previous_page']);
unset($data['previous_page']);
} elseif (\array_key_exists('previous_page', $data) && null === $data['previous_page']) {
$object->setPreviousPage(null);
}
if (\array_key_exists('page', $data)) {
$object->setPage($data['page']);
unset($data['page']);
}
if (\array_key_exists('links', $data)) {
$object->setLinks($this->denormalizer->denormalize($data['links'], 'JoliCode\\Harvest\\Api\\Model\\PaginationLinks', 'json', $context));
unset($data['links']);
}
foreach ($data as $key => $value_1) {
if (preg_match('/.*/', (string) $key)) {
$object[$key] = $value_1;
}
}
return $object;
}
public function normalize(mixed $object, ?string $format = null, array $context = []): array|string|int|float|bool|\ArrayObject|null
{
$data = [];
$values = [];
foreach ($object->getBillableRates() as $value) {
$values[] = $this->normalizer->normalize($value, 'json', $context);
}
$data['billable_rates'] = $values;
$data['per_page'] = $object->getPerPage();
$data['total_pages'] = $object->getTotalPages();
$data['total_entries'] = $object->getTotalEntries();
$data['next_page'] = $object->getNextPage();
$data['previous_page'] = $object->getPreviousPage();
$data['page'] = $object->getPage();
$data['links'] = $this->normalizer->normalize($object->getLinks(), 'json', $context);
foreach ($object as $key => $value_1) {
if (preg_match('/.*/', (string) $key)) {
$data[$key] = $value_1;
}
}
return $data;
}
public function getSupportedTypes(?string $format = null): array
{
return ['JoliCode\\Harvest\\Api\\Model\\BillableRates' => false];
}
}
} else {
class BillableRatesNormalizer implements DenormalizerInterface, NormalizerInterface, DenormalizerAwareInterface, NormalizerAwareInterface
{
use CheckArray;
use DenormalizerAwareTrait;
use NormalizerAwareTrait;
use ValidatorTrait;
public function supportsDenormalization($data, $type, ?string $format = null, array $context = []): bool
{
return 'JoliCode\\Harvest\\Api\\Model\\BillableRates' === $type;
}
public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool
{
return \is_object($data) && 'JoliCode\\Harvest\\Api\\Model\\BillableRates' === $data::class;
}
/**
* @param mixed|null $format
*/
public function denormalize($data, $type, $format = null, array $context = [])
{
if (isset($data['$ref'])) {
return new Reference($data['$ref'], $context['document-origin']);
}
if (isset($data['$recursiveRef'])) {
return new Reference($data['$recursiveRef'], $context['document-origin']);
}
$object = new \JoliCode\Harvest\Api\Model\BillableRates();
if (null === $data || false === \is_array($data)) {
return $object;
}
if (\array_key_exists('billable_rates', $data)) {
$values = [];
foreach ($data['billable_rates'] as $value) {
$values[] = $this->denormalizer->denormalize($value, 'JoliCode\\Harvest\\Api\\Model\\BillableRate', 'json', $context);
}
$object->setBillableRates($values);
unset($data['billable_rates']);
}
if (\array_key_exists('per_page', $data)) {
$object->setPerPage($data['per_page']);
unset($data['per_page']);
}
if (\array_key_exists('total_pages', $data)) {
$object->setTotalPages($data['total_pages']);
unset($data['total_pages']);
}
if (\array_key_exists('total_entries', $data)) {
$object->setTotalEntries($data['total_entries']);
unset($data['total_entries']);
}
if (\array_key_exists('next_page', $data) && null !== $data['next_page']) {
$object->setNextPage($data['next_page']);
unset($data['next_page']);
} elseif (\array_key_exists('next_page', $data) && null === $data['next_page']) {
$object->setNextPage(null);
}
if (\array_key_exists('previous_page', $data) && null !== $data['previous_page']) {
$object->setPreviousPage($data['previous_page']);
unset($data['previous_page']);
} elseif (\array_key_exists('previous_page', $data) && null === $data['previous_page']) {
$object->setPreviousPage(null);
}
if (\array_key_exists('page', $data)) {
$object->setPage($data['page']);
unset($data['page']);
}
if (\array_key_exists('links', $data)) {
$object->setLinks($this->denormalizer->denormalize($data['links'], 'JoliCode\\Harvest\\Api\\Model\\PaginationLinks', 'json', $context));
unset($data['links']);
}
foreach ($data as $key => $value_1) {
if (preg_match('/.*/', (string) $key)) {
$object[$key] = $value_1;
}
}
return $object;
}
/**
* @param mixed|null $format
*
* @return array|string|int|float|bool|\ArrayObject|null
*/
public function normalize($object, $format = null, array $context = [])
{
$data = [];
$values = [];
foreach ($object->getBillableRates() as $value) {
$values[] = $this->normalizer->normalize($value, 'json', $context);
}
$data['billable_rates'] = $values;
$data['per_page'] = $object->getPerPage();
$data['total_pages'] = $object->getTotalPages();
$data['total_entries'] = $object->getTotalEntries();
$data['next_page'] = $object->getNextPage();
$data['previous_page'] = $object->getPreviousPage();
$data['page'] = $object->getPage();
$data['links'] = $this->normalizer->normalize($object->getLinks(), 'json', $context);
foreach ($object as $key => $value_1) {
if (preg_match('/.*/', (string) $key)) {
$data[$key] = $value_1;
}
}
return $data;
}
public function getSupportedTypes(?string $format = null): array
{
return ['JoliCode\\Harvest\\Api\\Model\\BillableRates' => false];
}
}
}

@theteknocat can you please test the branch associated with #47 in your environment to check that it works well?

If you do not mind, I am going to merge #47 and I'll let you close this one?
In any case, thank you a lot for your help, it is very much appreciated!

@theteknocat
Copy link
Author

@xavierlacot @finwe thanks for your responses and for flagging the correct way to do this. I had no idea how to wonk with the Jane php api, so this is definitely the better solution and having a compatibility layer that works with both versions is ideal.

Of course this now creates a conflict with the commit I made to the manually updated generated code, but that can be reverted easily enough. I'll try to find some time in the next few days to test this in my environment and see if it works.

@theteknocat
Copy link
Author

@xavierlacot after updating my codebase to use v7.0, everything works as expected. Thanks so much for taking care of that!

@theteknocat theteknocat closed this Apr 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Error in JaneObjectNormalizer after updating symfony/serializer to 7.x
3 participants