-
-
Notifications
You must be signed in to change notification settings - Fork 921
Swagger subresource + OperationPathResolver refactor proposal #1245
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
Conversation
cd66784
to
1af17e5
Compare
1af17e5
to
f188c27
Compare
I like that idea ;p Do you want some help on this ? |
continue; | ||
} | ||
|
||
$subresource = $propertyMetadata->getSubresource(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subResource
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope it's subresource
everywhere :p.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but it feels awkward
It's almost done, just few tests to add! I just want to validate the |
f188c27
to
e2020a4
Compare
@@ -43,8 +43,9 @@ public function getConfigTreeBuilder() | |||
->scalarNode('title')->defaultValue('')->info('The title of the API.')->end() | |||
->scalarNode('description')->defaultValue('')->info('The description of the API.')->end() | |||
->scalarNode('version')->defaultValue('0.0.0')->info('The version of the API.')->end() | |||
->scalarNode('default_operation_path_resolver')->defaultValue('api_platform.operation_path_resolver.underscore')->info('Specify the default operation path resolver to use for generating resources operations path.')->end() | |||
->scalarNode('default_operation_path_resolver')->defaultValue('api_platform.operation_path_resolver.generator')->info('[Deprecated] Specify the default operation path resolver to use for generating resources operations path.')->end() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to deprecate a configuration?
|
||
<service id="api_platform.operation_path_resolver.dash" class="ApiPlatform\Core\PathResolver\DashOperationPathResolver" public="false"> | ||
<deprecated>The "%service_id%" service is deprecated since ApiPlatform 2.1 and will be removed in 3.0. Use PathNameGenerator instead.</deprecated> | ||
</service> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the operation_path_resolver
is still valid. I just want to deprecate those:
operation_path_resolver.underscore
operation_path_resolver.dash
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed
Almost there. The current code is backward compatible with the pre-2.1 OperationPathResolver's! Tests will be red because of deprecations (will fix later). I'd like your help on naming things 🕺 :
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
@@ -43,8 +43,9 @@ public function getConfigTreeBuilder() | |||
->scalarNode('title')->defaultValue('')->info('The title of the API.')->end() | |||
->scalarNode('description')->defaultValue('')->info('The description of the API.')->end() | |||
->scalarNode('version')->defaultValue('0.0.0')->info('The version of the API.')->end() | |||
->scalarNode('default_operation_path_resolver')->defaultValue('api_platform.operation_path_resolver.underscore')->info('Specify the default operation path resolver to use for generating resources operations path.')->end() | |||
->scalarNode('default_operation_path_resolver')->defaultValue('api_platform.operation_path_resolver.underscore')->info('[Deprecated] Specify the default operation path resolver to use for generating resources operations path.')->end() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's being added, but it's not merged yet: symfony/symfony#22382. For now you can use this trick: symfony/symfony#21051 (comment)
</service> | ||
|
||
<service id="api_platform.operation_path_resolver.custom" class="ApiPlatform\Core\PathResolver\CustomOperationPathResolver" public="false"> | ||
<!-- @TODO should be "api_platform.operation_path_resolver.generator" when the default is removed --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you remove the @todo
annotation? It triggers annoying warnings in SensioLabs Insight.
@@ -28,7 +28,6 @@ | |||
class RouteNameGenerator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you make this make this class final
btw?
* | ||
* @author Antoine Bluchet <[email protected]> | ||
*/ | ||
class DashPathNameGenerator implements PathNameGeneratorInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
final
*/ | ||
public function create(string $resourceClass): array | ||
{ | ||
$cacheKey = self::CACHE_KEY_PREFIX.md5(serialize([$resourceClass])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just using $resourceClass
as the cache key? It will be faster (if /
must be escaped, you can use str_replace
).
return $cacheItem->get(); | ||
} | ||
} catch (CacheException $e) { | ||
// do nothing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe can you return $subresourceOperations
here to prevent the call to isset
later?
$visiting = "{$parentOperation['property']}-{$parentOperation['resource_class']}-$property-$subresourceClass"; | ||
|
||
foreach ($parentOperation['identifiers'] as $key => list($param, $class)) { | ||
$prefix .= 0 === $key ? "$class" : "-$param-$class"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Useless quotes around "$class"
.
namespace ApiPlatform\Core\Operation; | ||
|
||
/** | ||
* Generate a path name according to a string and whether it needs pluralization. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generates
if ($operationType === OperationType::ITEM) { | ||
$path .= '/{id}'; | ||
} | ||
@trigger_error(sprintf('Method %s() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1.', __METHOD__), E_USER_DEPRECATED); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this deprecation necessary if the class itself is deprecated?
if ($operationType === OperationType::ITEM) { | ||
$path .= '/{id}'; | ||
} | ||
@trigger_error(sprintf('Method %s() will have a 4th `string $operationName` argument in version 3.0. Not defining it is deprecated since 2.1.', __METHOD__), E_USER_DEPRECATED); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
|
interface PathNameGeneratorInterface | ||
{ | ||
/** | ||
* Transforms a given string to a tableized, pluralized string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PHPDoc summary is wrong here, since this is the interface.
f835b3b
to
80fa3ca
Compare
@@ -19,6 +19,7 @@ | |||
|
|||
/** | |||
* @author Amrouche Hamza <[email protected]> | |||
* @group legacy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Insight on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you paste the error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a lot of deprecations because of the UnderscoreOperationResolver class deprecation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our own code shouldn't trigger deprecations. Can you paste the stack trace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remaining deprecation notices (220)
The use of ApiPlatform\Core\PathResolver\UnderscoreOperationPathResolver is deprecated since 2.1. Please use PathSegmentNameGenerator instead: 219x
219x in SwaggerCommandTest::testExecute from ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\Command
The "api_platform.operation_path_resolver.default" service is deprecated since ApiPlatform 2.1 and will be removed in 3.0. Use PathSegmentNameGenerator instead: 1x
1x in SwaggerCommandTest::testExecute from ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\Command
Legacy deprecation notices (62)
This makes phpunit exit with code 1
. We're still using UnderscoreOperationPathResolver
, should I already remove the service use in the code? If I do so, it will lead to breaking changes.
Or I can just change the api_platform.operation_path_resolver.default
but then again, BC break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok got it. It's fine this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also having a lot of this deprecation notices. The library shouldn't trigger it, is there any way to use the new version without BC ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// if (isset($v['default_operation_path_resolver'])) { | ||
// @trigger_error('The use of the `default_operation_path_resolver` has been deprecated in 2.1 and will be removed in 3.0. Use `path_name_generator` instead.'); | ||
// } | ||
// })->end(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this hack be added to the rootNode
or elsewhere?
ee9bd7f
to
7b9c5de
Compare
I found some bugs while trying this on the framework package, still working on improving the Get the
|
682b437
to
81a279d
Compare
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getSegmentName(string $name, bool $pluralize = true): string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like the $pluralize
argument. It should be up to the implementation to decide whether they want to pluralize or do other things. What we need to provide here is the context (e.g. whether this is for a collection or item).
f602688
to
ddc3ccd
Compare
ddc3ccd
to
1dd4bdb
Compare
1. Implement SubresourceOperationFactory 2. Deprecates UnderscoreOperationPathResolver/DashOperationPathResolver in favor of PathSegmentNameGenerator 3. Fix `toOne` relations by not using identifiers 4. Implement Swagger subresources with the correct prefix
1dd4bdb
to
e109a25
Compare
Thank you very much @soyuka! |
} else { | ||
return $this->deferred->resolveOperationPath($resourceShortName, $operation, OperationTypeDeprecationHelper::getOperationType($operationType), $operationName); | ||
if (null !== $operationName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} elseif (OperationType::SUBRESOURCE === $operationType) {
throw ...
} elseif (null !== $operationName) {
$routName = ...
} else {
return ...
}
😛
@soyuka What method would you recommend using to handle access authorization to a subresource ? |
@soyuka please give an example. where to define it? parent or child entity? maybe on property? |
@soyuka when I define it like this on child entity it seems it does not call my voters at all
|
@soyuka But if I do
It does work. A bit not obvious, I would say. |
Yes you have to give the correct operation name and it's not easy to find/guess... Your second example is the good one. Sorry about the delay I'm on vacation. |
Swagger subresource + OperationPathResolver refactor proposal
1.
OperationPathResolverInterface
Okay, after lot of thinking here's my proposal about the whole OperationPathResolver mess.
Initially OperationPathResolver was implemented because some users want to use
-
instead of_
in their paths. Because of this simple need, we introduced a complicated decoration pattern.My proposal would be to deprecate the use of the
OperationPathResolverInterface
if all we want is to use a dash instead of an underscore.Instead, I've introduced a simple
PathNameGenerator
who's signature looks like this:This class will be configurable the same way as is the
OperationPathResolver
but it won't compute paths. Instead, it's only used to name things.What about
UnderscoreOperationPathResolver
andDashOperationPathResolver
then? They're still working and there's no breaking change here but I think we should deprecate them in favor of a this new "naming service". Indeed, we don't need to generate a path, all we want is to use-
or_
to format our path.2.
SubresourceOperationFactory
With subresources complexity (recursion, start/end-points) we need to be able to retrieve a Subresource
path
orroute_name
from a givenResourceClass
with ease. To do so, I've implemented aSubresourceOperationFactory
(thanks @Simperfit) that will generate the operations from a givenresourceClass
.This is better then using a
OperationPathResolver
based onOperationType
and is less complex to implement.This new class is currently used :
ApiLoader
to add routes to the symfony routerSwagger\DocumentationNormalizer
to provide swagger docsNote that
Subresources
are NOT compatible withOperationPathResolver
s! Still, it's usingPathNameGenerator
and subresources paths could be written with dashes instead of default underscores.Because the subresource feature is not in the stable release yet I think it's fine. Still, if one wants dashes, he would've to use
PathNameGenerator
.Thanks at @meyerbaptiste @Simperfit for the talks around this issue.
@dunglas this refactor is needed for a stable release because the current state of handling subresource paths is too messy IMO.
TODO: