Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Fix strict typing exception when the propertyName is a number #1055

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

Merged
merged 2 commits into from
Apr 13, 2017
Merged

Fix strict typing exception when the propertyName is a number #1055

merged 2 commits into from
Apr 13, 2017

Conversation

jocel1
Copy link
Contributor

@jocel1 jocel1 commented Apr 13, 2017

Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets api-platform/api-platform#282
License MIT
Doc PR

@@ -63,7 +63,7 @@ public function create(string $resourceClass, array $options = []): PropertyName
// Properties
foreach ($reflectionClass->getProperties() as $reflectionProperty) {
if (null !== $this->reader->getPropertyAnnotation($reflectionProperty, ApiProperty::class)) {
$propertyNames[$reflectionProperty->name] = true;
$propertyNames[$reflectionProperty->name] = (string)$reflectionProperty->name;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we keep keys? $propertyNames[(string) $reflectionProperty->name] should work no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I studied this a bit more, looks like the fix should be in PropertyNameCollection:

--- a/src/Metadata/Property/PropertyNameCollection.php
+++ b/src/Metadata/Property/PropertyNameCollection.php
@@ -30,7 +30,9 @@ final class PropertyNameCollection implements \IteratorAggregate, \Countable
      */
     public function __construct(array $properties = [])
     {
-        $this->properties = $properties;
+        $this->properties = array_map(function($property) {
+            return (string) $property;
+        }, $properties);
     }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the key unfortunately php is converting the key to int, even when (string) is forced

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, still:

<?php

$t = [];
$t[118] = 'foo';
$t['bar'] = 'foo';

var_dump(array_map(function($v) {
    return (string) $v;
}, array_keys($t)));

Outputs:

array(2) {
  [0]=>
  string(3) "118"
  [1]=>
  string(3) "bar"
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup a centralized array_map is definitely better to handle this issue

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fond of the centralized array_map solution. It looks hackish... This is not the reponsibility of PropertyNameCollection to fix the data provided by friend classes. Other classes should provide data respecting the contract (an array of strings).

@soyuka
Copy link
Member

soyuka commented Apr 13, 2017

For the test, I'd recommend to create a new fixture class (avoid editing Dummy, too many tests are based on it at one change will require lots of changes :p).
You can add a test in this class by using the new fixture, would be just fine!

Copy link
Member

@dunglas dunglas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like your solution. It's elegant and faster than array_map. I just left a minor comment regarding the useless cast. Thank you very much for fixing this!

@@ -63,7 +63,7 @@ public function create(string $resourceClass, array $options = []): PropertyName
// Properties
foreach ($reflectionClass->getProperties() as $reflectionProperty) {
if (null !== $this->reader->getPropertyAnnotation($reflectionProperty, ApiProperty::class)) {
$propertyNames[$reflectionProperty->name] = true;
$propertyNames[$reflectionProperty->name] = (string)$reflectionProperty->name;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$reflectionProperty->name is a always a string, so the cast isn't necessary (same everywhere).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we can make this even faster by using $propertyNames[] = $reflectionProperty->name; if we rely on values :).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really because we must ensure that properties are unique. If you use values, you'll need to call in_array and it's an O(n) operation instead of O(1).

@@ -63,7 +63,7 @@ public function create(string $resourceClass, array $options = []): PropertyName
// Properties
foreach ($reflectionClass->getProperties() as $reflectionProperty) {
if (null !== $this->reader->getPropertyAnnotation($reflectionProperty, ApiProperty::class)) {
$propertyNames[$reflectionProperty->name] = true;
$propertyNames[$reflectionProperty->name] = $reflectionProperty->name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key may be useless now ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not, it ensures the uniqueness.

@jocel1
Copy link
Contributor Author

jocel1 commented Apr 13, 2017

I've just pushed the required tests

@soyuka
Copy link
Member

soyuka commented Apr 13, 2017

@jocel1 may you change the target branch to 2.0 and rebase? (If you're not sure about how to rebase lmk).

@jocel1 jocel1 changed the base branch from master to 2.0 April 13, 2017 15:45
@jocel1
Copy link
Contributor Author

jocel1 commented Apr 13, 2017

rebase & squash done

@@ -81,7 +81,7 @@ public function create(string $resourceClass, array $options = []): PropertyName
}

if (null !== $propertyName && null !== $this->reader->getMethodAnnotation($reflectionMethod, ApiProperty::class)) {
$propertyNames[$propertyName] = true;
$propertyNames[$propertyName] = (string) $propertyName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cast can be removed too.

@@ -41,7 +41,7 @@ public function create(string $resourceClass, array $options = []): PropertyName

// Inherited from parent
foreach ($this->decorated->create($resourceClass, $options) as $propertyName) {
$propertyNames[$propertyName] = true;
$propertyNames[$propertyName] = (string) $propertyName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cast can be removed.

Copy link
Contributor Author

@jocel1 jocel1 Apr 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mm no, this is this one in my case which was causing the issue : the symfony component PropertyInfoExtractor::getProperties() called through the PropertyInfoPropertyNameCollectionFactory returns an int instead of a string

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the Symfony component suffers from the same bug. We may keep this fix temporarily but we should fix this behavior in Symfony as well then bump the minimal version required by API Platform.

Do you want to handle this? If you're out of time I can open the Symfony PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you can handle this one, I'm definitely out of my time ;)

@dunglas
Copy link
Member

dunglas commented Apr 13, 2017

Travis and AppVeyor seem to have some troubles. Can you rebase and push force again?

@dunglas dunglas merged commit 1365e44 into api-platform:2.0 Apr 13, 2017
@dunglas
Copy link
Member

dunglas commented Apr 13, 2017

Thank you very much @jocel1!

fabpot added a commit to symfony/symfony that referenced this pull request Apr 13, 2017
…(dunglas)

This PR was merged into the 2.8 branch.

Discussion
----------

[PropertyInfo] Prevent returning int values in some cases

| Q             | A
| ------------- | ---
| Branch?       | 2.8
| Bug fix?      | yes
| New feature?  | no <!-- don't forget updating src/**/CHANGELOG.md files -->
| BC breaks?    | no
| Deprecations? | no <!-- don't forget updating UPGRADE-*.md files -->
| Tests pass?   | yes
| Fixed tickets | api-platform/api-platform#282, api-platform/core#1055
| License       | MIT
| Doc PR        | n/a

PHP automatically converts array keys to an int if and only if it looks like an int... When a getter looks like `get123`, the ReflectionExtractor returns an array containing an int instead of a string. This PR fixes this.

Commits
-------

b190ec2 [PropertyInfo] Prevent returning int values in some cases.
@teohhanhui teohhanhui added the bug label Apr 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.