Skip to content
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

Allow overriding routes #2577

Merged
merged 7 commits into from
Feb 28, 2021
Merged

Allow overriding routes #2577

merged 7 commits into from
Feb 28, 2021

Conversation

SychO9
Copy link
Member

@SychO9 SychO9 commented Jan 27, 2021

Fixes #2553

Changes proposed in this pull request:
Store registered routes in an array before applying them to FastRoute, thus allowing extensions to replace them (as described in the issue).

Reviewers should focus on:
The default route / is a special route, it is dynamically set in ForumServiceProvider after flarum.forum.routes has been resolved, at which point, extensions have already registered their routes, which means it's the one route they cannot override.
That said, I don't think there's a problem with that, they should not be directly overriding this route, instead they should be adding an option for a homepage route like tags.

TODO

Confirmed

  • Backend changes: tests are green (run composer test).

Copy link
Sponsor Member

@askvortsov1 askvortsov1 left a comment

Choose a reason for hiding this comment

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

Should we allow directly overriding, or might it be clearer to require that a route be somehow unset? This would prevent accidentially overriding routes by copying route names.

We should also test that this fixes https://github.com/flarum/core/issues/2239

}

public function getRouteData()
{
if (empty($this->reverse)) {
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

Should we allow this (and the same with getPath)? Perhaps we could throw an exception instead to further discourage early resolution?

Copy link
Member Author

Choose a reason for hiding this comment

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

so, we would essentially apply the routes on the boot phase by manually resolving the route collection, instead of on first demand. That would technically work, I'm just unsure if it's a good idea to take early resolution into account and explicitly throw an exception just to discourage extension devs.

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

That's a good point... Plus, now that:

  • Classes registered via extenders will be resolved when needed instead of at subscribe time
  • Subscribers will be resolved after boot

early resolution should be much, much less frequent. Yay extenders!!!

@SychO9
Copy link
Member Author

SychO9 commented Jan 28, 2021

Should we allow directly overriding, or might it be clearer to require that a route be somehow unset? This would prevent accidentially overriding routes by copying route names.

Yup, that's why it's a draft, I have yet to add the ability to remove a route, which means we'll have to throw an exception if a route is overridden but already exists.

Wasn't sure at first, but I do favour the more explicit way of overriding a route. (by having to remove it first)

@SychO9
Copy link
Member Author

SychO9 commented Feb 4, 2021

one thing that's bothering me, is that adding an integration test for not being able to add an already existing route didn't work, there seems to be an issue with expecting the exception.

@SychO9 SychO9 marked this pull request as ready for review February 4, 2021 17:14
src/Extend/Frontend.php Show resolved Hide resolved
@@ -59,6 +60,13 @@ public function route(string $path, string $name, $content = null)
return $this;
}

public function removeRoute(string $name)
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

I don't like that this is in both extenders, but I don't suppose we have a choice?

Copy link
Member Author

Choose a reason for hiding this comment

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

well, Frontend adds this type of content routes, I thought it'd makes sense to be able to remove them here as well, especially since the method is always GET here, so it needn't be a parameter.

But technically, using the Routes extender to remove these routes will still work I believe.


foreach ($routeDatas as $routeData) {
$this->dataGenerator->addRoute($method, $routeData, ['name' => $name, 'handler' => $handler]);
if (isset($this->routes[$method][$name])) {
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

Shouldn't we have unique names regardless of method?

Copy link
Member Author

Choose a reason for hiding this comment

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

While it makes sense for the names to be unique, regardless of the method, and for extension developers to always use unique route names as it is good practice. FastRoute doesn't error out when same route names are used, or even same method and route names, it only errors out when the same path is provided.

Which means, that any extensions that have used similar route names, but with different methods would break if we don't take the method into account.
Here's an example: https://github.com/v17development/flarum-seo/blob/master/extend.php
Search: https://github.com/search?l=PHP&p=3&q=Flarum+Extend+Routes+get+-repo%3Aflarum%2Fapi-docs&type=Code

Although, if there are any extensions that used the same route name and method with a different path, they would break with this implementation as well, I just find it less likely for an extension to have done that, but I haven't it it up (I'm not how I'd look that up either)

Copy link
Sponsor Member

Choose a reason for hiding this comment

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

Since the URL Generator is based on unique route names per-app, I would prefer that we enforced unique route names in each app. Any extensions that use the same route name are improperly implemented, and I'd prefer that we break this now than later.

Alternatively, we could do this in phases: method + name unique for this release, just name unique for next release?

Copy link
Member Author

Choose a reason for hiding this comment

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

Alternatively, we could do this in phases: method + name unique for this release, just name unique for next release?

I would be in favour of this, we would warn extension devs that non unique route names will no longer work in the next release.

tests/integration/extenders/RoutesTest.php Outdated Show resolved Hide resolved
src/Http/RouteCollection.php Show resolved Hide resolved
[ci skip] [skip ci]
@askvortsov1 askvortsov1 merged commit ea840ba into master Feb 28, 2021
@askvortsov1 askvortsov1 deleted the sm/allow-overriding-routes branch February 28, 2021 19:01
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.

Flarum\Forum\Content\Discussion overriding extension settings Allow overriding routes
4 participants