Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Abstract the code from block visibility for the current path check to be a condition plugin. I already have code for this and will clean it up and post it shortly with tests attached. I'll be extracting the php portion of this into its own plugin.
Eclipse
Parent Issue:
Comment | File | Size | Author |
---|---|---|---|
#165 | interdiff.txt | 509 bytes | kim.pepper |
#165 | 1921544-current-path-condition-165.patch | 9.64 KB | kim.pepper |
#162 | interdiff.txt | 7.15 KB | kim.pepper |
#162 | 1921544-current-path-condition-162.patch | 9.64 KB | kim.pepper |
#155 | 1921544-psr4-rerolled.patch | 8.99 KB | xjm |
Comments
Comment #1
larowlanAny progress here?
Comment #2
EclipseGc CreditAttribution: EclipseGc commentedok, this patch contains the patch from #1965836: The Condition Manager Needs the Namespace just to keep stuff working, it is dependent on that patch going in.
This plugin was a lot of fun because it's actually expecting injection of classes (Request and the class at path.alias_manager) so I'm really looking forward to the implementation code to make this work. It should be a ton of fun. but this is the basic requirement for the time being.
Eclipse
Comment #3
EclipseGc CreditAttribution: EclipseGc commentedTagging to get Crell to look at this.
Comment #4
EclipseGc CreditAttribution: EclipseGc commentedremoved the portions of the patch that have been committed to head in another issue.
Comment #5
EclipseGc CreditAttribution: EclipseGc commentedFixed a couple documentation things. No code changes. Since no one is actively reviewing this patch yet, I'm not providing interdiff ;-)
Comment #6
jibranDo we need to check
my/pass/*
path?Comment #7
EclipseGc CreditAttribution: EclipseGc commentedok, wildcard testing then :-)
Eclipse
Comment #8
jibranThanks you @EclipseGc. Patch looks fine to me. Everything looks great.
After doing little poking around in the core I finally understand
I going to RTBC a "Stalking Crell" issue :).
Comment #9
katbailey CreditAttribution: katbailey commentedNot so fast ;-)
EclipseGC mentioned this to me this morning and I said I'd have a look tonight - I already see some problems with it (it shouldn't be special-casing the alias manager as this is only one example of something that messes with the incoming path - it should use the path processor manager instead) which I will elaborate on tonight.
Comment #11
EclipseGc CreditAttribution: EclipseGc commentedI'm calling lies on that failure.
Comment #12
EclipseGc CreditAttribution: EclipseGc commented#7: 1921544-7.patch queued for re-testing.
Comment #13
katbailey CreditAttribution: katbailey commentedSorry for the vague comment earlier and unfortunately I still haven't had much time to spend on this (had hoped to throw together a test to show the problem I'm referring to) but my main concern is this: since #1910318: Make path resolution the responsibility of a series of PathProcessor classes, rather than one PathSubscriber class, the alias manager is no longer singled out as the one thing that alters the inbound path. Rather, we have a series of inbound path processors that act in sequence on the request path to resolve it to the system path. The alias manager is just one of the processors in this chain. You could have an arbitrary path processor that specifies that the path 'foo/bar' should resolve to 'some/path/alias' which in turn resolves to 'node/1'. If the path condition specified for a particular block was that it should show on 'foo/bar', then this would not work with the current setup as it would only check the condition against the system path and the path alias.
So what I'm thinking is that this plugin should get the path processor manager injected into it instead of the alias manager. But we'd need to make some changes so that the path processor keeps track of the various path resolutions along the way and exposes a
getInboundPathResolutions()
method or something, and then the condition would be checked against each one. Here is the PathProcessorManager class: http://drupalcode.org/project/drupal.git/blob/ea909a162c195e50271685a09c...The
drupal_match_path()
logic should either be moved into the condition plugin if all other uses of it in core will be converted to uses of this plugin, or else it should be a method on the path processor manager, which is a service so we could keep drupal_match_path as a wrapper function around a call toDrupal::service('path_processor_manager')->matchPath()
for other procedural code that still needs it.That then just leaves
drupal_strotolower()
as the only other procedural function being called here which I'm not sure what to do about but it would be nice to get rid of it.Anyway, I hope this makes sense and that I am not over-thinking it. It would be good to get Crell's thoughts on this too.
Comment #14
effulgentsia CreditAttribution: effulgentsia commentedSimilar to my question in #1921540-42: Create a User Role Condition, how will this integrate with block caching? When this condition is used to affect what's in a block, then we'll want to cache the block by the request path, but not by, say, the client IP address, which is also part of $request. However, if we're saying the condition requires an entire $request object, then how does the SCOTCH controller know that path will be used (and therefore needs to factor into caching), but IP address won't be? Related: #1965990: Figure out how to integrate hooks, $request, and caching.
Comment #15
effulgentsia CreditAttribution: effulgentsia commentedtagging
Comment #16
pameeela CreditAttribution: pameeela commented@Crell are you able to weigh in on #13? EclipseGc is awaiting confirmation before moving down that path.
Comment #17
Crell CreditAttribution: Crell commentedThis can now be replaced with Unicode::strtolower(), which is slightly less fugly.
Ibid.
This may be scope creep, but is there any way to turn drupal_match_path() into a service we can just inject here? It would be such a nice little service.
In fact, that would likely help resolve Kat's concern about aliases vs. path processors. That becomes that service's problem, and it can take the path processor manager as a dependency.
My other concern is passing in the request object directly, because I'm always nervous when passing the request object to something. Is there no way to pass in just a path, which then gets passed over to the service above and it takes care of mangling it as needed?
Comment #18
kim.pepperComment #19
kim.pepperI haven't quite got this working. I haven't ventured into plugins and annotions land yet, so there might be something obvious someone else can help with?
Still need to convert everything else to use a PathMatcher service.
Comment #20
Crell CreditAttribution: Crell commenteddrupal_static() should never be used inside a class. Just save things to an object property.
This should be injected.
Comment #22
kim.pepperAdded a factory and injecting the
PathMatcher
into theRequestPath
rather than trying to usegetContextValue()
. Also made changes as per #20.Comment #24
kim.pepper#22: 1921544-current-path-condition-22.patch queued for re-testing.
Comment #26
kim.pepperThe plugin (request_path) did not specify an instance class. in Drupal\Component\Plugin\Factory\DefaultFactory::getPluginClass() (line 62 of /var/lib/drupaltestbot/sites/default/files/checkout/core/lib/Drupal/Component/Plugin/Factory/DefaultFactory.php)
Not sure what I have got wrong here?
Comment #27
kim.pepperTalked with @dawehner at Drupalcon who told me about ContainerFactory, so we are using that to allow dependencies to be injected.
Also, need to Change ContainerFactory to check for existence of create method, as it's not always there.
Comment #29
kim.pepperNeed to use correct method signature for create and ensure that the parent constructor is called correctly.
Comment #31
dawehnerI nearly that you could write a php unit test, but then something called t() :(
Comment #32
tim.plunkettInstead of using reflection, can we have a ContainerPluginInterface with create() on it?
Comment #33
kim.pepperYes we should, and use class_implements('ContainerPluginInterface') instead. Can we do this in a follow up?
K
Comment #34
kim.pepperFixed typo contruct => construct as well as some clean ups.
Post here to get some help from @dawehner at the sprint.
Comment #35
dawehnerYou had the plugin in the wrong directory && mixed up the context ...
Comment #37
dawehner#35: durpal-1921544-35.patch queued for re-testing.
Comment #38
kim.pepperThanks @dawehner!!
Comment #39
dawehnerWhat about just storing the frontpage string in the pathMatcher but inject the ConfigFactory?
Comment #40
kim.pepperOnly store the default front page as per #39.
Comment #41
kim.pepperWe need to fix up the tests to use injection. We aren't using the alias_manager from the plugin context anymore.
Comment #42
kim.pepperI stuffed up and #40 didn't include #35 :-(
This does, and removes the setContext from the test as its now injected. :-)
Comment #43
dawehnerThen please
Now we can remove that again.
Comment #44
kim.pepperRemoves unused annotation in #43.
Comment #45
dawehnerYeah the standard is just a little bit different.
Comment #46
kim.pepperTalked with @katbaily and @Crell about this issue at Drupalcon Portland, and agreed that we would keep PathMatcher as a service.
Also talked with @eclipsegc and agreed that we would not use ContainerFactory, and instead pass the alias_manager, and path_matcher services in via context.
I'll work on this while waiting in the LAX transit lounge and hopefully have a patch today.
Comment #47
kim.pepperThis reverts all the use of ContainerFactory and dependency injection, and instead used context to get the needed dependencies for alias_manager and path_matcher as per #46.
It still uses the PathMatcher as this was agreed to be the best current solution.
(BTW airport wifi sucks).
Comment #48
EclipseGc CreditAttribution: EclipseGc commentedThis is definitely starting to move more the right direction. I'll give this greater attention once I make it back home, however could you mark drupal_match_path() as being deprecated? I'm pretty sure that's the right thing to do here as you create and convert to, this class.
Eclipse
Comment #49
kim.pepperRe-rolled and marked drupal_match_path as deprecated.
Comment #50
katbailey CreditAttribution: katbailey commentedThis looks fine to me for now as we agreed to punt on the bigger question of whether to stop special-casing the alias manager for things like this and use the path processor manager instead.
I made an attempt to convert the test to a unit test before realizing this is completely impossible until #1813762: Introduce unified interfaces, use dependency injection for interface translation and #1903346: Establish a new DefaultPluginManager to encapsulate best practices have landed. And actually, dawehner pointed this out already in #31 :-P
Comment #51
fagoThe path manager context? What should a user configure to go in there?
No, dependencies should stay what they are: a dependency. Contextual data that a conditions needs to work is something different. So this should use regular dependency injection, e.g. via the static createInstance() method as for other plugins.
Comment #52
kim.pepperHi @fago,
@eclipsegc, @crell, @katnbailey and had a discussion on this at the sprint, and believe we got closer to an understanding of the difference between plugins that are re-used in different 'contexts' (e.g. conditions) and those that are not (e.g. in views). The former should not be dependency injected, but the latter can be.
I think @eclipsegc probably needs to chime in here and make the same point he made to us.
Comment #53
EclipseGc CreditAttribution: EclipseGc commented@fago,
I've attempted to point out that any use of the service container to satisfy plugin "dependencies" is actually a tight coupling between that plugin and the Drupal use case. We don't need to do that, the context system is robust enough and satisfying those dependencies can be done other ways. I'd have had the conversation in Portland if I had realized we weren't yet on the same page here. Apologies.
The user isn't going to choose anything, the given wrapping code for a plugin type use case will have a facility to satisfy this without tightly coupling the individual plugins to a particular factory that will always instantiated them with registered instances in the service container. I realize this particular plugin's class dependencies aren't likely to ever need to be something else, but the approach would prevent us from building say, a condition system that used a different database connection. My approach would not limit us that way.
The patch itself looks sane to me. We should pursue Kat's mentioned single class solution for the path matching stuff, but it's a nice to have, so I'm cool with this. RTBC.
Eclipse
Comment #54
fagoYes, but we've the problem already solved with #1863816: Allow plugins to have services injected - in a different way. So why do we need another solution based upon contexts for conditions/actions/..?
The problem with mixing it into the context is that there is no logic any more that connects the context with the service in a general way. E.g. how we'd Rules figure out which service to connect to the context and how would it figure out which contexts would have to be hidden from the UI because they are just dependencies in reality?
Yep, a pity we missed that. I've not realized that either :/
Comment #55
tim.plunkettI'm with fago on this one, I had no idea we would be using context for DI. That makes absolutely no sense to me.
I came here after seeing this kind of thing in action in #2003482: Convert hook_search_info to plugin system.
Comment #56
msonnabaum CreditAttribution: msonnabaum commentedWIth fago and tim.plunkett. This is insanity. It's bad enough we can't have contexts injected via arguments, let's please not try to pass dependencies into the same system.
Also, the "slave database" needs to stop being used as the sole use case for doing crazy things.
Comment #57
tim.plunkettHardcoding the class names directly is overkill, bypasses the DIC completely, is hard to read, and is a ton more work.
In addition, you now have to cope with being coupled to the container. From #2003482: Convert hook_search_info to plugin system:
Following how the rest of all Dependency Injected code in core works, that would be:
You now have the full advantages of OO and an IDE and when you want the entity manager, instead of calling
You can call
Comment #58
larowlan+1 context is for injecting user supplied context, like the language object in the language plugin, or an array of roles in the role plugin, not for services - that's my 2c™
I see context as equivalent to say arguments in a hook_rules_action_info definition. You define what context the user must provide, either by the UI or otherwise. Stuff that is non-negotiable like services etc are not the concern of the user, the plugin should interact with the container to receive these.
Comment #59
dawehnerYes, context allows you to inject both bits, and theoretically also use service names instead of using classes but what do we really gain?
People will write controllers and plugins very often, so consistency on how to inject the services is a win.
Comment #60
Crell CreditAttribution: Crell commentedLet me see if I can articulate what I *think* EclipseGc's point here is, and thereby formulate a response.
The plugin system at its core is Drupal agnostic. This is a good thing. That means it also has no inherent coupling to the Symfony DependencyInjection component. This is also a good thing.
In practice, though, plugin instances have dependencies. In particular, there are 2 things they depend on:
Type 1 is handled by the Context portion of the API, which is, really, just a bunch of wrappers and generic methods to set stuff by name. It works well enough for that, and I don't think there's a debate there.
The tricky part is type 2; Kris' argument is "it's not tricky, just use the same generic API, problem solved." The counter-point is "providing services like that is what the DIC is for, damn well use it."
To have a concrete example, suppose we have a key/value lookup plugin type. At runtime you give it a string, and it returns some other string. We have two implementations:
Nothing about implementation A is inherently tied to Drupal; Guzzle and strings are not Drupal-specific, so the plugin itself shouldn't be either. Keeping that decoupled from Drupal is a worthy goal, and one that we've been pushing for in many places.
However, it's not the plugin implementation that is the issue; it's the plugin manager that instantiates it. That needs to:
While the plugin can indicate its need for Guzzle as a constructor parameter (constructor injection), that doesn't provide enough information for the manager to know at runtime what object to give it. It could specify it via an annotation, but in what format? How does the manager know that it needs a guzzle object (or, rather, something implementing Guzzle's connection interface) to pass into it? And, more pointedly, once it knows that then how does it know where to get the connection from itself?
I do not see how re-using the context API as a form of generic setter injection solves that problem; the manager still needs to get a guzzle object from somewhere, and needs to know that it needs to do so.
Additionally, consider implementation B. It needs a DB connection, specifically a Drupal DBTNG connection. Right there, it's dependent upon Drupal (or at least on DBTNG). At that point independence from Drupal becomes largely theoretical. Now, I am all for theoretical purity; I've argued for it many times quite loudly. :-) But as a practical matter, I don't see how this theoretical purity is actually achieved.
So the part that I'm missing, and have always been missing, is that using Context API as a generic setter injection does not in fact divorce the entire plugin system from Drupal; It only divorces the plugin implementation, mostly, but not the plugin manager. The plugin manager is, 90% of the time, probably still container aware because otherwise I have no idea how you would implement the example above. And if merging service injection into Context API doesn't actually get us the Drupal-decoupling we want (and I think we all want that at this point, to the maximum degree feasible), then why shoe-horn those two systems together in the first place?
That is, Plugins as a concept are Drupal-agnostic, but a specific application of them (pretty much anyone that is going to have dependent services) in many cases cannot be. That plugin type would be coupled to some mechanism of acquiring services to inject, be it the Symfony DIC (which couples it to Symfony, not Drupal, technically), Zend's DIC implementation (about which I know next to nothing other than it exists), a Pimple instance (if you were using, say, Silex), or whatever.
If such shoe-horning does in fact provide that complete decoupling in some way that I don't understand, Kris, please provide a trivial implementation of the above example in a way that is Drupal agnostic and DIC agnostic but still achieves the goal of plugin classes that are fully injected (either with Guzzle or a DB connection). We need to be seeing code here, not speaking in generic terms, because otherwise we're going to continue talking past each other. If you think this issue is the wrong place to do so, please put it somewhere else that we can link to and reference. (Feel free to copy as much of this comment as you'd like to explain the sample case.)
Comment #61
EclipseGc CreditAttribution: EclipseGc commented@Crell,
Thank you for that, you got most of the way there, and I totally appreciate the mental efforts you went to there both in thinking it through and documenting it. You've described the problem well, and most of the solution as well, so it's really just a matter of going a little further here. With regard to code, I'll see what I can do, but I think pwolanin's stuff is actually an ok example of what the solution COULD look like.
In terms of the goal of divorcing plugins from Drupal, yes I've attempted to do that where ever possible, however actual plugins meant to run inside drupal (such a Conditions) are already using say... form api, so divorcing it from drupal would be folly at best. The bigger issue here is divorcing it from Drupal's specific use case. The problem here lies in what a DIC registered string/class pairing actually is. When we use the static create() return static(); approach, we end up in a situation where the plugin is not practically usable separate from that coupling. Yes there are ways to make it usable, but they all require a ridiculous amount of work. As you mentioned, the context system functions as a form of setter injection, and if dependencies are annotated as contexts, then they suddenly become overridable. Most people don't know it, but context actually supports constructor injection as well (as peter's code that tim pasted above is demonstrating). All that to say, my objective here is to just give particular plugin types the ability to be reused without a tight coupling to various drupal services.
Looking at Peter's code directly for a second, what he's actually doing isn't much different from what the traditional ContainerFactory approach is doing EXCEPT that I don't have to subclass the plugin(s) to change their dependencies out. I'm still not fond of the ContainerFactory approach, but this methodology of satisfying dependencies largely removes most of my objections and seems a simple enough way forward, so in terms of showing code, what Peter has provided here is not insane.
My intents were for the plugin managers to actually begin asking any module that provided plugins for defaults through some sort of alterable hook type process. That would allow individual implementations wrapping the plugin manager to swap out these dependency contexts earlier in the process before plugins are even instantiated. I was never really happy with any of the solutions I had, but they'd have all worked, and none of them would have tightly coupled a given plugin to the implementation in the service container. Peter's approach to all of this could actually be abstracted and automated to a certain degree. I think it'd be easy enough to just agree on context keys being service ids, and if no context is passed, get the key automatically in the constructor and set the context. Again this is done so that the context can be swapped out later, an approach that the current ContainerFactory makes VERY difficult (Not the actual code in the factory, just the agreed upon approach thus far).
To illustrate how this could be changed relatively easily for the whole system, I think we could do: https://gist.github.com/EclipseGc/5677953
This then basically agrees that plugin context annotations keys double as service id fallbacks. If a context is not present during construction, then the service id is checked and instantiated if available. This should be a relatively simple change, and I expect wouldn't even cause current plugins using this plugin base class to change since most of them are overriding this method. They could convert or not, it should be a trivial change for them. This satisfies my efforts because I'm no longer screaming about tight coupling to the container that cant' be overridden.
In short, it doesn't really matter how much you'd like me to stop using the database as the example. Nor is it really relevant how unlikely we ever are to swap out the alias manager. What matters here is that we have a system that CAN do that. Our early attempts at doing it are obtuse, sure, but I just wrote 1 method that solves my major issues, and still functions mostly the way you all have been operating.
Finally, yes, we should likely be having this conversation elsewhere, but this code's not going in apparently until we solve this, which is a pity, but I digress. Let's just solve it here.
Eclipse
Comment #62
neclimdulbusy morning so I was only able to skim not give the full read i wanted. My concern at least with the example given is that configuration and plugin definitions are static information. Modifying them from the canonical values is questionable and something left to site builders to modify behaviors not to implement core interactions. If you want some sort of context things like that it should be an additional argument to the constructor. I see it as valid that the create method would populate that with objects from the container using values from configuration or plugin definitions though.
I don't think modules really make sense as context and should be their own constructor object but something like this.
$context['modules'] = $container->get($configuration['module_handler_key']);
To expand on that last sentenct a bit, in my mind the idea of context(at least for this argument) is configurable arguments for plugins. Things that aren't configurable like module lists we will use normal DI concepts and pass them to constructors using arguments. Configurable DI through context I could see either being arguments or maybe this context array concept.
Comment #63
EclipseGc CreditAttribution: EclipseGc commentedIn case it wasn't clear, any context that isn't leveraging typed data, will not be user configurable. The important part here is that the developer be able to impose sane alternate dependencies w/o going to an extreme effort wise.
Eclipse
Comment #64
katbailey CreditAttribution: katbailey commentedAs per our long irc discussion today I am re-rolling this to use a container aware factory, borrowing from timplunkett's patch here #1863816-123: Allow plugins to have services injected.
I have it almost done - just trying to figure out the test, will get back to it tomorrow...
Comment #65
katbailey CreditAttribution: katbailey commentedSo I went with a PHPUnit test in the end, which means it only tests the actual plugin itself, not the manager / factory integration.
Comment #66
dawehnerThis patch seems to contains bits of #1863816: Allow plugins to have services injected
Afaik the service is called "path.alias_manager.cached"
No reason for these empty lines.
Comment #68
kim.pepperComment #69
tim.plunketthttp://drupalcode.org/project/drupal.git/commitdiff/75ee363 went in!
Comment #70
katbailey CreditAttribution: katbailey commentedAwesome! I'll try and get this rerolled tonight.
Comment #71
katbailey CreditAttribution: katbailey commentedRerolled now that #1863816: Allow plugins to have services injected is in, fixed the problem with the other Condition API integration tests (not in the interdiff, it was just a bad use statement), and addressed #66, although using the 'path.alias_manager' service instead of 'path.alias_manager.cached' because it makes no difference in this case and the latter may be going away soon.
Comment #73
tim.plunkett#71: 1921544-current-path-condition-71.patch queued for re-testing.
Comment #74
tstoecklerDouble space here.
Leaving at needs review. Looks good otherwise, but I didn't really look very thoroughly.
Comment #75
kim.pepperRe-rolled since #1903346: Establish a new DefaultPluginManager to encapsulate best practices went in. Fixed spacing issue in #74.
Comment #76
jibranI ma not going to RTBC again after 68 comments a lot has changed but IMO it is ready.
Comment #77
tim.plunkettThe code itself is good, just some docs/standards stuff:
I don't think we use @see after @deprecated, the second line should be indented two spaces (like @todo) and should read more like a sentence
Might as well be a oneliner
We use $regex everywhere, not $regexp, so let's make this $regexes (I honestly thought it was a typo when I read this.
Needs the full class name.
Missing blank line.
Checks
@return bool
Drop the "value: " part.
Swap the order of these two
Split these on multiple lines
Missing a bunch of @params
Comment #78
kim.pepperFixes code style/doc issues in #77
Comment #79
tim.plunkettThanks, code looks good!
Comment #80
pwolanin CreditAttribution: pwolanin commentedShould we be moving towards matching the route and params instead of the path?
Comment #81
dawehnerThe problem is that users maybe will not have access to the route names. It seems to be way to technical for them.
Comment #82
catchUsers won't have access to the route names - but the whole point of having a router + generator is being able to move routes around without path-specific code breaking. I think this could use more discussion - i.e. should we open a follow-up to add a route condition?
Comment #83
pwolanin CreditAttribution: pwolanin commentedA good step would be switching the front page variable to actually store a route name + params? In that case and others I guess we'd find the route based on the path when the setting is saved?
Comment #84
dawehnerI am wondering whether we can change APIs once something is in core, at this state?
Comment #85
kim.pepper#78: 1921544-current-path-condition-78.patch queued for re-testing.
Comment #87
kim.peppertagging Needs reroll
Comment #88
kim.pepperRe-roll of #78
Comment #89
jibranCreated #2071553: Create route and params condition for #82. RTBC as per #79.
Comment #90
kim.pepper#88: 1921544-current-path-condition-88.patch queued for re-testing.
Comment #91
kim.pepper#88: 1921544-current-path-condition-88.patch queued for re-testing.
Comment #92
webchickPatch no longer applies.
Comment #93
arnested CreditAttribution: arnested commentedRerolled.
Fixed a few code style issues.
Comment #95
arnested CreditAttribution: arnested commentedThe patch applies clean but fails phpunit with:
I think I narrowed it down to the fact that Drupal\Core\Plugin\ContextAwarePluginBase.php does:
Fixed both in the attached patch.
and that we already have a PluginBase in Drupal\Core\Plugin\PluginBase.php
Another thing: Shouldn't the RequestPath condition annotate itself as a condition?
Comment #96
arnested CreditAttribution: arnested commentedComment #97
kim.pepper#95: 1921544-current-path-condition-95.patch queued for re-testing.
Comment #98
dawehnerWe might should add some docs on there.
We could also inject the string_translation service and wrap it with a t method.
Is there a reason why we don't mock the interface directly? AliasManagerInterface
It seems to make sense to split up these tests into multiple test methods.
Comment #99
kim.pepperThanks dawehner!
Not sure if this plugin is still relevant post api freeze? How will it be used?
Comment #100
EclipseGc CreditAttribution: EclipseGc commentedyes it's still relevant. The entire condition plugin system is in core, and it works great, if we can finish these conversions then we have some greater potential moving forward if D8 chooses to use semantic versioning.
Eclipse
Comment #101
kim.pepperThis does everything suggested in #98 except for 4). I wanted to see if tests passed before splitting them all up.
Comment #102
kim.pepperForgot to include the Interface name in the mock. Tests pass locally.
Comment #103
kim.pepperThis takes care of splitting out the test methods as per #98.
Comment #104
dawehnerLet's add a @group Drupal and maybe an @see of the tested class.
Comment #105
kim.pepperGood idea. I also cleaned up the imports.
Comment #106
dawehnerThank you!
Comment #107
fagoI just had a short look at it, and it looks mostly good. However:
Thats seems weird to me. If it's multiple patterns, why isn't it an array of patterns?
The parsing of the condition configuration string is surely not the responsibility of the general-purpose path matcher service?
Is this something the path matcher should handle? Are paths with different capitalization generally speaking equal?
Setting to needs work for the 1.
Comment #108
fagoComment #109
kim.pepperFago you're right about 1. And the units tests are all really testing PathMatcher. I'll have a go at moving them all over to a PathMatcher unit test.
Not sure about 2.
Comment #110
EclipseGc CreditAttribution: EclipseGc commentedPaths with different caps are different in different OSes, i.e. windows paths should be case sensitive (if I recall correctly). I'm not sure how Drupal has historically handled that.
Eclipse
Comment #111
kim.pepperI've created a new phpunit test class for PatchMatcher and copied the tests over there. This means we can remove some of the tests from the RequestPath condition plugin, but need to check which ones.
Also, I've updated the matchPath() interface to take an array, which I think makes a lot more sense for an interface. Got lost in regex land so ended up just imploding on newline and re-using the existing code. Would be great if someone could offer suggestions on how to improve this. :-)
Comment #112
Crell CreditAttribution: Crell commentedThis can be collapsed to:
$pages = array_map('trim', explode("\n", $this->configuration['pages']));
For case-insensitivity questions, see: #2075889: Make Drupal handle incoming paths in a case-insensitive fashion for routing
I think the only reason drupal_match_path() took a string was that the block config form saved patterns as a big string, and rather than build an API we just built a utility function that we pretended was an API. :-) Array makes more sense here.
Comment #113
kim.pepperFixes 1) in #112
Comment #114
kim.pepper113: 1921544-current-path-condition-112.patch queued for re-testing.
Comment #116
kim.pepperTaggging
Comment #117
neclimdulNo changes just fixes the service conflict.
Comment #118
kim.pepperKick the bot
Comment #120
Xano117: 1921544-current-path-condition-117.patch queued for re-testing.
Comment #122
kim.pepper117: 1921544-current-path-condition-117.patch queued for re-testing.
Comment #124
kim.pepperThe service definition "path_matcher" does not exist.
Comment #125
kim.pepperRe-added missing service definition.
Comment #127
kim.pepperDrush installer works, but UI installer fails.
Comment #128
kim.pepperNeed to manually add PathMatcher in the installer.
Comment #129
EclipseGc CreditAttribution: EclipseGc commentedWhy's the path_matcher being added to core.services.yml twice? Also, I question whether that class is even required, I think you might be looking for the router.route_provider service. See if that works for you, if not, we'll dig in a little further.
Eclipse
Comment #130
dawehnerYou seemed to have merged in another patch (preload config objects).
@EclipseGC We do support actual a different usecase here. This does not directly interfere with routing.
<3
We should rather use path.alias_manager.cached instead.
Comment #131
kim.pepperComment #132
tim.plunkettInventing a new tag.
Comment #133
kim.pepperShould we move out the PathMatcherInterface into a separate issue?
Comment #134
kim.pepperRe-rolled against a load of changes. Also, This is built on top of #2268801: Update ConditionInterface to use recently added plugin interfaces.
Discussed with @tim.plunket in IRC and agreed to remove the PathMatcher interface and service and make it a followup.
Comment #136
kim.pepperTests need to use RequestStack too.
Comment #138
kim.pepperRe-roll since #2268801: Update ConditionInterface to use recently added plugin interfaces went in.
Since we've gone back to calling drupal_match_path, I've stubbed that out of our unit tests so we don't need to call it.
Comment #140
kim.pepper138: 1921544-current-path-condition-138.patch queued for re-testing.
Comment #142
kim.pepperNeed to set match to true by default.
Comment #143
tim.plunkettLooks good overall. Just some things leftover because the issue is so old:
Not needed anymore, use the trait.
Can't this just be getMock()?
$this->getStringTranslationStub()
Comment #144
kim.pepperThanks Tim. Fixes for #143. Also since we are not calling drupal_match_path anymore, removed stub config that it used.
Comment #145
kim.pepperI've split off the PathMatcher service to #2272201: Move drupal_match_path in path.inc to a service
Comment #147
EclipseGc CreditAttribution: EclipseGc commentedI spent a bunch of time debugging this today. The drupal_match_path() is never called because it exists in an include (path.inc) that is not currently included when this is run, and so it's calling out to an undefined function. You can't include the path.inc cause other unit tests have defined functions that exist within that include already in order to pass their own tests... (grrrr)
In short I think it'd be better to do this as an integration test instead of a unit test. Too much of the request code flow exists within Drupal proper currently to be a unit test.
Eclipse
Comment #148
kim.pepperHi Eclipse,
I've actually stubbed out the call to drupal_match_path in the unit tests. However, I take your point on needing an integration test. Hopefully just extending KernelTestBase.
K
Comment #149
kim.pepperContextAwarePluginBase is already using that trait.
Comment #150
kim.pepperComment #151
kim.pepperI've moved the plugin to the correct namespace, and moved all tests over to a new test extending KernelTestBase so we are now interacting with drupal_match_path etc.
I've also made the request a context parameter, as this makes it a lot easer for testing, and keeps it in line with how context is being used in the other plugins.
Comment #152
tim.plunkettThat looks much better.
I think this can go
Extra line here
You should implement defaultConfiguration(), provide '' as a default, and skip the !empty check
These are indented too far. I know phpstorm likes to do that
Comment #153
kim.pepperThanks @tim.plunkett! Fixes for #152.
Comment #154
tim.plunkettExcellent! Thanks @kim.pepper!
Comment #155
xjmComment #156
kim.pepperComment #157
kim.pepperTests are passing after PSR-4 re-roll. Putting back to RTBC.
Comment #158
fagohm, I must say I'm unsure about the context specified as class only. How would someone make use of it and provide the context in a general fashion?
Comment #159
hass CreditAttribution: hass commentedI guess I asked my the same. I see a very good use case here in general for block visibility and code visibility in Google Analytics. I'm also using the same logic like block visibility, but it would be great if the code is maintained only once in core and I can just reuse it and get rid of _google_analytics_visibility_pages() and maybe _google_analytics_visibility_roles(), too.
Comment #160
kim.pepperThe general approach we've discsussed in IRC is to put anything that is being evaluated in context (e.g. request, user role, etc.). You could inject the request stack, but I thinks this makes the usage pattern a lot clearer. See the tests for examples of how you would pass it in.
Comment #161
fagoThink about it, I think that is what makes sense to me. Either, it's just a dependency or it's required context which the user needs to be able to configure. If it's a dependency, it should be injected, if it should be conifugrable we should have sufficient metadata for the context needed, i.e. a type, label etc.
Setting back to needs work as this needs more discussion.
Comment #162
kim.pepperFago and I discussed this at Drupalcon. I guess I don't really understand context, and it appears that this isn't the right usage.
I've reverted back to using a request_stack.
Comment #163
kim.pepperCreated a follow up #2278541: Refactor block visibility to use condition plugins
Comment #164
fagoThe change looks good to me. As discussed with eclipsegc one can argue whether a request should be defined as context, but as said above - if so we should use our regular way to define it. I'm fine with adding this without a request context.
outdated comment.
Comment #165
kim.pepperGreat! Fixes comments in #164.
Comment #166
fagook, back to RTBC then.
Comment #167
znerol CreditAttribution: znerol commentedAs per #2124749: [meta] Stop using $request->attributes->get(MAGIC_KEY) as a public API we shouldn't longer rely on the
_system_path
request attribute. Is there a reason why we cannot use$request->getPathInfo()
here?Comment #168
tim.plunkettUntil #2239009: Remove public direct usage of the '_system_path' request attribute goes in, this is still fine.
Comment #169
znerol CreditAttribution: znerol commentedStill we could use
$request->getPathInfo()
and not introduce another_system_path
dependency in the first place. Was this considered at any point?Comment #170
znerol CreditAttribution: znerol commentedPlease ignore my comments. I had the impression that this introduces a new dependency on the
_system_path
request attribute. Instead the changes here only make the existing dependency more explicit, which is a good thing.Comment #171
alexpottCommitted acb97e8 and pushed to 8.x. Thanks!
Comment #172
tim.plunkettQuick follow-up.
#2283061: RequestPath condition uses non-existent service path.alias_manager.cached