Updated: Comment #0
Suggested commit message
Issue #1918768 by larowlan, tim.plunkett, chx: Refactor tour module to use routes instead of paths.
Problem/Motivation
Tour module relies on paths to decide when to display each tour.
In the new world order we should be using route names.
Proposed resolution
Switch out paths for route names
Remaining tasks
Reviews
User interface changes
None
API changes
Change to tour yml format
Related Issues
Original report by @username
Over in #1809352: Write tour.module and add it to core we need config entity queries where we can do path matching, this patch provides pattern matching on single value properties.
Would also nice to be able to have pattern matching on array properties too (tour config entity has a path array property on the entity and contains wildcards - ala the 'pages' textarea on the block placement configuration form).
Here's an example patch cobbled together after conversations with @chx.
Commit credit for @chx too as he rightly pointed out that I should be using preq_quote() and some inconsistencies in my tests.
Comment | File | Size | Author |
---|---|---|---|
#48 | Screen Shot 2014-01-22 at 23.02.46.png | 99.2 KB | vijaycs85 |
#47 | tour-1918768-47.patch | 15.55 KB | tim.plunkett |
#47 | interdiff.txt | 809 bytes | tim.plunkett |
Comments
Comment #1
larowlanSample implementation
Comment #2
chx CreditAttribution: chx commentedYou dont need backslashes. And I am confused by the goals here, isn't it $condition['value'] that needs to be converted into a regex and preg_matched against value? But then again, your 'label' is 'foo_bar_*' -- this is really weird. I would've expected the label to be foo_bar_baz and the condition('label', 'foo_bar_*', 'MATCH').
Comment #3
damiankloip CreditAttribution: damiankloip commentedYes, I'm confused too. I'm with chx; I was expecting to match 'foo_bar_baz' with condition('label', 'foo_bar_*'). You need to use wildcards in actual properties and not for querying them?
EDIT: I see now, you want to essentially replace the drupal_match_path() usage. These tests should test against the array values too? Still seems weird :)
Comment #4
larowlanYeah, we did have wildcards in our properties - ala paths in block config eg node/add/*
Comment #5
larowlanSo Tour entity has a paths property which is an array.
I was hoping we could use the Conditions API for this but I've not seen any movement on those issues.
#1921540: Create a User Role Condition
#1921546: Create a PHP Filter Condition
#1921550: Create a Language check Condition
and especially
#1921544: Create a Current Path Condition
The paths property contains wildcards.
Eg
We want to match entities where a known condition (eg
current_path()
) matches any of that entity's property.So in this case we're comparing current_path() to Drupal\tour\Plugin\Core\Entity\Tour->paths
Hope that helps
Comment #6
dawehnerI am wondering whether we could convert the paths to actual used route names, which then potentially would be way faster to load.
Comment #7
larowlanYes I think that would work but it would entail
Comment #8
clemens.tolboomI don't think ask Tour writers to enter route names as that knowledge is not available for a writer. It's no big deal to write a path to route lookup I guess.
But one blocker against this issue is writing a tour for very particular paths like
Anyway I filed Tour UI #2099305: Check for router path and prepare for change notice to come.
Comment #9
larowlanComment #10
larowlanLike so
Comment #12
larowlan10: tour-route-name..patch queued for re-testing.
Comment #13
andypostI'm agree with #8 - that "tour-writers" have no clue about route names so tour should work with both, probably tour_ui module could try to convert path to route name
Comment #14
damiankloip CreditAttribution: damiankloip commentedWe should use the controller directly here instead?
Comment #15
alexpott@damiankloip - this is in procedural code, therefore looks fine to me
Comment #16
kim.pepper10: tour-route-name..patch queued for re-testing.
Comment #18
tim.plunkettThere is \Drupal::entityQuery(), a bit shorter. But why not use entity_load_multiple_by_properties() here?
Comment #19
larowlanentity_load_multiple_by_properties() performs an equality test, what we want is an in_array() test
re-roll
Comment #20
tim.plunkettUgh, I forgot how bad ConfigStorageController::loadByProperties() is. We should fix that (not here).
Here's a fix for the entityQuery part, and the Views UI.
Comment #21
nick_schuch CreditAttribution: nick_schuch commented20: tour-1918768-20.patch queued for re-testing.
Comment #22
dawehnerI wonder whether we also should provide some support for route parameters.
Comment #23
kim.pepperdawehner, so that we could have different tours depending on a dynamic parameter? Not sure what the use case for this would be.
Comment #24
larowlan@kim see comment at #8
Comment #25
nick_schuch CreditAttribution: nick_schuch commentednode/1 vs node/2? Sounds like this one needs work.
Comment #26
larowlanthanks to @chx for helping me sort the EFQ syntax here.
Comment #27
tim.plunkettThe methods I know of that are prefixed with match* don't return Booleans. I think hasRoute() would be a better name.
While the ->has() method is nice, it is weird to see ParameterBag here. It makes it more cumbersome to call this method, and couples it to HttpFoundation. I think this should just call ->all() on the bag before passing it in, and use an array typehint.
This would also make it easier to unit test
Comment #28
larowlandiscussed on irc ::hasMatchingRoute() is best name
Comment #29
larowlanAlso needs an update to tour.schema.yml
Comment #30
vijaycs85Had a word with @larowlan: config can be something like https://gist.github.com/vijaycs85/8550098
Comment #31
larowlanFixes 27-30
Comment #32
tim.plunkettThis seems like it could be useful to other modules. Maybe move it to system?
Comment #33
larowlandamn, had it there first (got to stop second guessing myself)
moved
Comment #35
larowlan33: tour-route-name.33.patch queued for re-testing.
Comment #36
tim.plunkettCan we get a unit test for this?
Comment #37
larowlanAdds unit test, had to switch from accessing the protected to using getRoutes in the hasMatchingRoute method so I could mock the getRoutes method.
Also moved the static into a protected property and added a reset method cause un-resettable statics are pants.
Comment #38
tim.plunkettWe usually put the group on the class.
Why not getMock('Drupal\tour\TourInterface')? Just curious here.
We should always use assertSame() (strict comparison)
I love when unit tests lead to better code!
Comment #39
larowlan1. ok
2. cause we're testing the getMatchedRoutes implementation, which isn't on the interface
3. ok
Comment #40
larowlanComment #42
larowlanComment #43
larowlan2. cause we're testing the hasMatchingRoute implementation, which isn't on the interface
Comment #44
larowlanTests added
Comment #45
tim.plunkettTo clarify, that method does live on the interface.
I forgot about the setMethods() functionality of getMockBuilder, which allows you to use the actual methods in \Drupal\tour\Entity\Tour except the ones you choose to mock. So we're good here.
These are missing commas.
The unit test does not cover this case. Just need to add a provider case for all non-matching route names
Comment #46
larowlandone
Comment #47
tim.plunkettThe trailing period on your @covers prevents that from working.
I've switched it to use @coversDefaultClass as we've done elsewhere. That will make any other methods we add later even easier.
Since I'm just changing some PHPUnit directives, I'm still going to RTBC this. Awesome work @larowlan!
Comment #48
vijaycs85Validated with config_inspector + sample views ui config to verify config schema and seems good. Ref: attachement. +1 for RTBC.
Comment #49
alexpottCommitted 1560601 and pushed to 8.x. Thanks!
Handbook page https://drupal.org/node/1934442 needs updating.
Removed this empty space during commit.
Comment #50
larowlanUpdated handbook page