I hope there isn't an issue for this already, so here goes.

This patch just splits off the link generator and url generator to a common trait. It then refactors FormBase, ControllerBase, and BreadcrumbBase to use it.

Comments

Crell’s picture

Issue summary: View changes

Wow, it worked! :-)

I checked again and it doesn't look like any other base classes are using this pattern, so this is complete. Yay, easy conversions! Please review/RTBC.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Looks valid.

vijaycs85’s picture

  1. +++ b/core/lib/Drupal/Core/Breadcrumb/BreadcrumbBuilderBase.php
    @@ -7,57 +7,16 @@
    -  protected function l($text, $route_name, array $parameters = array(), array $options = array()) {
    
    +++ b/core/lib/Drupal/Core/Controller/ControllerBase.php
    @@ -232,32 +227,6 @@ protected function formBuilder() {
    -  public function l($text, $route_name, array $parameters = array(), array $options = array()) {
    

    Looks like we got different visibility and now it is protected? are we sure, no need for tests?

  2. +++ b/core/lib/Drupal/Core/Routing/LinkGeneratorTrait.php
    @@ -0,0 +1,108 @@
    +  public function url($route_name, $route_parameters = array(), $options = array()) {
    

    Only public method in this trait is url(), but name is LinkGeneratorTrait and not UrLGeneratorTrait?

Crell’s picture

Status: Reviewed & tested by the community » Needs work

It doesn't make sense to me to have separate traits for l() and url() since they are closely related. LinkAndUrlGeneratorsTrait seems like a silly name, so I went with the one with fewer acronyms. :-)

Re visibility, we should normalize that. StringTranslationTrait has the "useful" methods protected, and the override setters public. LinkGeneratorTrait should do the same. I'll see about fixing that tonight unless someone wants to beat me to it. (Please do!)

Crell’s picture

Assigned: Unassigned » Crell
Status: Needs work » Needs review
StatusFileSize
new10.84 KB
new1.2 KB

Fixed the protected/public issue and added a docblock to the trait itself.

vijaycs85’s picture

Thanks again @Crell. It looks good to me. +1 to RTBC. Created #2283385: Remove BreadcrumbBuilderBase as followup to remove the base class.

Crell’s picture

Can you mark it back to RTBC then? :-)

vijaycs85’s picture

Status: Needs review » Reviewed & tested by the community

Ok then :)

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 5: 2282161-link-generator-trait.patch, failed testing.

znerol’s picture

I'm working on maintenance mode over at #2288665: Remove _maintenance request attribute and replace it with a maintenance mode service and #2288911: Use route name instead of system path in user maintenance mode subscriber. It looks like the various MaintenanceModeSubscriber might profit from an url-generator trait. In those classes it would be very helpful to also have the ContainerBase::redirect() method in the trait. On the other hand l() is completely unnecessary there.

A quick grep through the code base excluding yml, api.php, vendor, tests, interfaces and Drupal.php containing procedural wrappers turns up the following result: LinkGenerator is mentioned in 3 files, UrlGenerator in 29 files. Only two files are common (ControllerBase.php and LinkGenerator.php).

This raises the following questions:

  1. It is probably debatable whether kernel-event subscribers qualify as application-level code. Opinions?
  2. Is there a chance that the the ContainerBase::redirect() method is moved into the trait also?
  3. Given that URL generator seems to be used much more often than the link generator, shouldn't we provide separate traits?
Crell’s picture

Whether kernel event listeners are application or not: Hm. There was a lengthy discussion about that a while back that didn't come to a resolution. effulgentsia did an audit of listeners we had at the time. This isn't really the right place to re-have it, though.

redirect() belongs only in the Controller, as you have to return a redirect object; it's not just for formatting a string. Triggering a redirect in most non-Controller places is a code smell. From an event listener specifically there's nowhere to return it, except maybe setting a Response object on the event. That's sufficiently rare that I don't think the shortcut is needed, certainly not with the SL cost it incurs.

We could split it out I guess; I just didn't see much cause to do so. But... I guess they're wrapping 2 different services, so if we want one trait per wrapped service... Meh, I guess so.

Crell’s picture

Status: Needs work » Needs review
StatusFileSize
new12.23 KB
new6.21 KB

Sigh. Broken by the serialization trait. Rerolled.

Also went ahead and split the trait in two. No other changes. Let's see if I got the usages right...

Status: Needs review » Needs work

The last submitted patch, 12: 2282161-link-generator-trait.patch, failed testing.

Crell’s picture

Status: Needs work » Needs review
StatusFileSize
new12.3 KB
new797 bytes

Yep, I forgot one.

effulgentsia’s picture

Patch looks good. Just a couple questions:

+++ b/core/lib/Drupal/Core/Routing/LinkGeneratorTrait.php
@@ -55,9 +48,22 @@ protected function l($text, $route_name, array $parameters = array(), array $opt
   protected function linkGenerator() {
...
+++ b/core/lib/Drupal/Core/Routing/UrlGeneratorTrait.php
@@ -0,0 +1,69 @@
+  protected function urlGenerator() {

When we added the StringTranslationTrait, we renamed the service getter method from translationManager() to getStringTranslation(). Along the same lines, should we prefix a "get" onto these two?

+++ b/core/lib/Drupal/Core/Routing/UrlGeneratorTrait.php
@@ -0,0 +1,69 @@
+ * Services registered
+ * in the Container should not use this trait but inject the appropriate service
+ * directly for easier testing.

This relates to #10.1 and the desire to use this trait within an event subscriber in #2288911: Use route name instead of system path in user maintenance mode subscriber. I agree that so long as the event subscriber is a service, which they all are pending #2023613: Move event registration from services.yml to events.yml, it should use constructor injection rather than a fallback to \Drupal::. However, couldn't it still use the trait along with CI (and e.g., ensure that by changing the setter to private)? If so, should we refine this comment to explain that?

Crell’s picture

StatusFileSize
new18.03 KB
new8.7 KB

15.1: Meh, renamed. Although that led me to discover (courtesy of PHPStorm's refactoring command) a whole bunch of places that were accessing that method rather than using url() and l() and such directly. I fixed most of those. The only ones I left were 2 path-based lookups (which are bad anyway) 1) One that had a @todo on it for an issue that is not yet in (I didn't want to mess up a reroll for someone else) and 2) a path-based lookup for a node link, the route name for which is about to change via #2278567: Standardize node route names by relationship so I wanted to avoid the collission. That's an easy change for later.

15.2: I don't want to structure the comment around things that may or may not happen. It's already decently vague in saying "only use this if you're not in the container so constructor injection is annoyingly hard". ContainerInjectionInterface is just the most common example of that. As Tim pointed out to me the other day in chat, we have 4(!) static::create()-based interfaces. (That should get condensed...) The comment shouldn't tie deeply into the rest of the system architecture, just give a suggestion for when to use it.

sun’s picture

Status: Needs review » Reviewed & tested by the community

Patch contains some coding style issues, but we can polish coding style at any later point in time.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Can we get an issue to remove BreadcrumbBuilderBase

Committed c072353 and pushed to 8.x. Thanks!

  • alexpott committed c072353 on 8.x
    Issue #2282161 by Crell: Split off link/url generation trait.
    
vijaycs85’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.