8000 Add filter locator and deprecate filter collection by meyerbaptiste · Pull Request #1099 · api-platform/core · GitHub
[go: up one dir, main page]

Skip to content

Add filter locator and deprecate filter collection #1099

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 1 commit into from
May 15, 2017

Conversation

meyerbaptiste
Copy link
Member
Q A
Bug fix? no
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets N/A
License MIT
Doc PR N/A

First step before #1082 and #1083, we have to refactor the FilterCollection to avoid circular references with new filters.
Our solution is to use the PSR11 and a service locator. Thanks to http://symfony.com/blog/new-in-symfony-3-3-service-locators.

Copy link
Member
@soyuka soyuka left a comment

Choose a reason for hiding this comment

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

This is really nice work ❤️

try {
$filters[$filter] = $filterLocator->get($filter);
} catch (\Throwable $e) {
}
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't we use if ($filterLocator->has($filter)) {} instead of catching?


public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, Fil 8000 terCollection $filters)
public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, $filterLocator)
Copy link
Member

Choose a reason for hiding this comment

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

There is no such typing as ContainerInterface | FilterCollection in php right? Maybe we could document this new argument though.

Copy link
Member

Choose a reason for hiding this comment

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

same goes in the other classes with the same change

Copy link
Member Author

Choose a reason for hiding this comment

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

This works only for try/catch with PHP 7.1. I will add some PHPDoc.

Copy link
Member Author

Choose a reason for hiding this comment

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

I just made the change. Is it good for you like this?

Copy link
Member

Choose a reason for hiding this comment

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

👍 I hope that phpstan is fine with it and yeah this is better for future developers IMO. Thanks!

@@ -32,7 +32,7 @@
protected function extractPath(string $path)
{
try {
$resourcesYaml = Yaml::parse(file_get_contents($path));
$resourcesYaml = Yaml::parse(file_get_contents($path), Yaml::PARSE_KEYS_AS_STRINGS);
Copy link
Member

Choose a reason for hiding this comment

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

Hmm why this change? Did you hit a bug? This might need to be backported to 2.0 if it's the case.

Copy link
Member Author

Choose a reason for hiding this comment

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

I have deprecation warnings from the component without this change and tests fail...

Copy link
Member

Choose a reason for hiding this comment

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

oh okay this is because symfony 3.3 then alright! Thanks for the information.

Copy link
Member Author

Choose a reason for hiding this comment

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

@meyerbaptiste meyerbaptiste force-pushed the add_filter_locator branch 4 times, most recently from a3d11b5 to 30687bf Compare May 4, 2017 14:31
@meyerbaptiste
Copy link
Member Author

Tests fail because the master branch fails too.


<service id="api_platform.filter_collection_factory" class="ApiPlatform\Core\Api\FilterCollectionFactory" public="false" />

<service id="api_platform.filters" class="ApiPlatform\Core\Api\FilterCollection" public="false">
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like a good candidate for <defaults public="false" />

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, nice, I missed this feature! Thanks!

@soyuka
Copy link
Member
soyuka commented May 4, 2017

Tests fail because the master branch fails too.

Indeed, the Accept header isn't changing the format. This returns JSON-LD. It's weird, everything was green, then I just did composer update and it now fails.

Investigating but maybe @dunglas has a clue on this?

composer.json Outdated
@@ -23,7 +23,7 @@
"symfony/property-access": "^2.7 || ^3.0",
"symfony/property-info": "^3.3@beta",
"symfony/serializer": "^3.3@beta",
"willdurand/negotiation": "^2.0.3"
"willdurand/negotiation": "~2.2.0"
Copy link
Member

Choose a reason for hiding this comment

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

nice one maybe we can patch this in a separated pr?

Copy link
Member

Choose a reason for hiding this comment

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

Should be ~2.2.3 right?

Copy link
Member Author
@meyerbaptiste meyerbaptiste May 4, 2017

Choose a reason for hiding this comment

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

What about >=2.0.3 <2.3.0? BTW it's ~2.2.1!

Copy link
6D40
Contributor

Choose a reason for hiding this comment

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

^2.0.3 <2.3

@meyerbaptiste
Copy link
Member Author
meyerbaptiste commented May 4, 2017

Ok, I got it. The problem comes from the new release of willdurand/negotiation (2.3.0) and this commit: willdurand/Negotiation#92.

This was referenced May 5, 2017
@meyerbaptiste
Copy link
Member Author

Does anyone have an idea to fix/avoid that?

Generating code coverage report in PHP format ... done
Remaining deprecation notices (1)
The ApiPlatform\Core\Api\FilterCollection class is deprecated since version 2.1 and will be removed in 3.0. Implement the Psr\Container\ContainerInterface interface as service locator instead: 1x
    1x in CodeCovera
9E88
ge::start from SebastianBergmann\CodeCoverage

@chalasr
Copy link
Contributor
chalasr commented May 5, 2017

@meyerbaptiste CodeCoverage loads classes which causes the FilterCollection deprecation to be triggered. What you need is to move the deprecation to the constructor:

diff --git a/src/Api/FilterCollection.php b/src/Api/FilterCollection.php
index 32b1157..76af317 100644
--- a/src/Api/FilterCollection.php
+++ b/src/Api/FilterCollection.php
@@ -15,8 +15,6 @@ namespace ApiPlatform\Core\Api;
 
 use Psr\Container\ContainerInterface;
 
-@trigger_error(sprintf('The %s class is deprecated since version 2.1 and will be removed in 3.0. Implement the %s interface as service locator instead.', FilterCollection::class, ContainerInterface::class), E_USER_DEPRECATED);
-
 /**
  * A list of filters.
  *
@@ -26,4 +24,10 @@ use Psr\Container\ContainerInterface;
  */
 final class FilterCollection extends \ArrayObject
 {
+    public function __construct($input = [], $flags = 0, $iterator_class = \ArrayIterator::class)
+    {
+        @trigger_error(sprintf('The %s class is deprecated since version 2.1 and will be removed in 3.0. Implement the %s interface as service locator instead.', self::class, ContainerInterface::class), E_USER_DEPRECATED);
+
+        parent::__construct($input, $flags, $iterator_class);
+    }
 }

Or exclude this class from code coverage, I don't use coverage at all so I can't say if it's a good idea nor help.

@soyuka
Copy link
Member
soyuka commented May 5, 2017

Also you can mark specific tests as @group legacy and use @expectedDeprecation

@meyerbaptiste
Copy link
Member Author
meyerbaptiste commented May 5, 2017

It's what I made @soyuka but the problem here comes from coverage and not tests themselves.
But I think I will follow the @chalasr's suggestion and move my trigger_error() inside my constructor to avoid the deprecation notice during the coverage.

@chalasr
Copy link
Contributor
chalasr commented May 5, 2017

@soyuka comment made me think that maybe moving the @group legacy+@expectedDeprecation from the test methods to the top of the test class would solve it, unfortunately it does not. Either you have to trigger deprecations from constructors in order to don't have it triggered before construction, or the whole class should be excluded from the coverage, which I think is not a good idea as the class is still usable and well tested.

@meyerbaptiste meyerbaptiste force-pushed the add_filter_locator branch 7 times, most recently from 444b0a6 to fca4e6a Compare May 9, 2017 12:07
@@ -76,6 +76,7 @@ public function getIdentifiersFromItem($item): array
throw new RuntimeException(sprintf('No identifier found in "%s" through relation "%s" of "%s" used as identifier', $relatedResourceClass, $propertyName, $resourceClass));
}
}

Copy link
Member

Choose a reason for hiding this comment

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

Was fixed by 7dfdcb1

@@ -123,73 +123,67 @@ Feature: Create-Retrieve-Update-Delete
"hydra:totalItems": 1,
"hydra:search": {
"@type": "hydra:IriTemplate",
"hydra:template": "/dummies{?id,id[],name,alias,description,relatedDummy.name,relatedDummy.name[],relatedDummies,relatedDummies[],dummy,relatedDummies.name,order[id],order[name],order[relatedDummy.symfony],dummyDate[before],dummyDate[after],relatedDummy.dummyDate[before],relatedDummy.dummyDate[after],dummyFloat[between],dummyFloat[gt],dummyFloat[gte],dummyFloat[lt],dummyFloat[lte],dummyPrice[between],dummyPrice[gt],dummyPrice[gte],dummyPrice[lt],dummyPrice[lte],dummyBoolean,dummyFloat,dummyPrice,description[exists],relatedDummy.name[exists],dummyBoolean[exists]}",
"hydra:template": "\/dummies{?dummyBoolean,dummyDate[before],dummyDate[after],relatedDummy.dummyDate[before],relatedDummy.dummyDate[after],description[exists],relatedDummy.name[exists],dummyBoolean[exists],dummyFloat,dummyPrice,order[id],order[name],order[relatedDummy.symfony],dummyFloat[between],dummyFloat[gt],dummyFloat[gte],dummyFloat[lt],dummyFloat[lte],dummyPrice[between],dummyPrice[gt],dummyPrice[gte],dummyPrice[lt],dummyPrice[lte],id,id[],name,alias,description,relatedDummy.name,relatedDummy.name[],relatedDummies,relatedDummies[],dummy,relatedDummies.name}",
Copy link
Member

Choose a reason for hiding this comment

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

Not sure what went wrong here? If this is due to random sorting maybe we should sort everything to avoid such issues in the feature?

Copy link
Member

Choose a reason for hiding this comment

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

(we discussed this IRL with @meyerbaptiste).

Before: filters were in the same order than declared in services.yml
Now: filters are in the order the configuration in the resource.

It's not a BC break (the JSON parser should not depend of the order).
I prefer to not sort the filters, it allows to detect when we change the output, it's a desirable behavior.

*/
final class FilterCollection extends \ArrayObject
{
public function __construct($input = [], $flags = 0, $iterator_class = 'ArrayIterator')
{
@trigger_error(sprintf('The %s class is deprecated since version 2.1 and will be removed in 3.0. Implement the %s interface as service locator instead.', self::class, ContainerInterface::class), E_USER_DEPRECATED);
Copy link
Member

Choose a reason for hiding this comment

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

I would say Provide and implementation of "%s" instead.

{
private $filtersIds;

public function __construct(string ...$filtersIds)
Copy link
Member

Choose a reason for hiding this comment

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

Why not using an array?

Copy link
Member Author

Choose a reason for hiding this comment

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

Just a hack to have a typed array...

Copy link
Member

Choose a reason for hiding this comment

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

I prefer to use a raw array and use string[] in the PHPDoc, PHPStan will be able to check types using the PHPDoc.

Copy link
Member Author

Choose a reason for hiding this comment

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

Bad day for variadic functions 😭

Copy link
Contributor

Choose a reason for hiding this comment

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

if you really want a check you could also force it after in the code:

$filterIds = (function (string ...$filterIds) { return $filterIds; })(...$filterIds);

Or use a lib like https://github.com/beberlei/assert

Copy link
Member

Choose a reason for hiding this comment

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

We don't have to enforce this. The PHPDoc is the contract and it's an @internal class.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm just giving alternatives to enforce it, not saying you have to enforce it :P

@meyerbaptiste meyerbaptiste force-pushed the add_filter_locator branch 3 times, most recently from 34041be to ff3f1ba Compare May 10, 2017 14:51
@meyerbaptiste
Copy link
Member Author

All comments are fixed.

@dunglas dunglas merged commit 8622477 into api-platform:master May 15, 2017
@dunglas
Copy link
Member
dunglas commented May 15, 2017

Thanks @meyerbaptiste

@meyerbaptiste meyerbaptiste deleted the add_filter_locator branch May 15, 2017 13:11
@teohhanhui
Copy link
Contributor

Unfortunately, this must be reverted because bumping the required versions in composer.json is a major BC break. It means we suddenly drop support for a lot of people... 😞

@dunglas
Copy link
Member
dunglas commented May 17, 2017

@teohhanhui it's not, its allowed by semver (and we do this very often in Symfony). Note that we don't force to upgrade to new major versions, just to the last minor.

@teohhanhui
Copy link
Contributor
teohhanhui commented May 17, 2017

But if we're thinking in semver, 2.1 is not a major version. It's a minor version.

This is yet another reason (just realized this today) why I think Symfony does not really follow semver, despite their claims...

@dunglas
Copy link
Member
dunglas commented May 17, 2017

Semver is about code API. Not about dependencies. Every major project (including Symfony, Doctrine...) do this and this is totally acceptable. It's also the only way to no being stuck with very old and versions.
It's not a big deal for users to upgrade to a new minor version of a project. If they use the dependency themselves, it must be explicitly defined in their composer.json to prevent problems.

@teohhanhui
Copy link
Contributor

I don't know if we'll ever reach agreement about the technicality of whether bumping dependencies is a BC break, but in the spirit of semver, it'd be best if we can tag a major release when we drop support for an older minor version of Symfony.

In any case, stability flags only work at the project root level. So when we use @beta in require, that does nothing and will result in unfulfillable dependencies (because Symfony 3.3 is not released yet).

@dunglas
Copy link
Member
dunglas commented May 17, 2017

You're right about stability flags, but it's just a temporary solution. We'll not release 2.1 before the release of Symfony 3.3.

@teohhanhui
Copy link
Contributor

hoangnd25 pushed a commit to hoangnd25/core that referenced this pull request Feb 23, 2018
…cator

Add filter locator and deprecate filter collection
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants
0