Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
routing system
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
30 Jan 2015 at 22:18 UTC
Updated:
19 Mar 2015 at 18:34 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
webchickFWIW, I have no idea why we can't just use
path:here. It's what we called these things in D6/D7 (see screenshot of old UI at #2416987: Fix UI regression in the menu link form), it's shorter to type, and it was the other of the options catch approved in #2405551-86: Add a method to support UIs where users enter paths instead of route names and other valid use cases. Anything with "user" in it doesn't really make sense because, as evidenced by standard.install, these are not always user-entered paths at all.Comment #2
wim leers#1: because "path" as a URI scheme makes no sense, since "path" is also actually a component of every URI. So that'd mean we'd have to say funny things like :)
Comment #3
webchickFair enough, but does the fact that a confusing sentence might come up once in awhile outweigh the fact that this is going to totally confuse every developer who has to programmatically create a "hard-link"? And, given your -1 on
path:, how aboutrelative:?Comment #4
jibranHow about
base-uri:orbase-url:?Comment #5
cafuego commentedroot:? Less typing, and these paths are all relative from the drupal root, as far as I can tell. I also don't think root is used anywhere else yet.Comment #6
yched commentedraw:?unrouted:?Comment #7
almaudoh commenteddrupal:?? Had to say it :PComment #8
xjmSo keep in mind that we already have
base:for, e.g.,base:robots.txtin code. The point of this one is to denote user input. :)Comment #9
xjm@webchick:
All of the (very few) instances in core are actually for user-entered input stored in the database, or test coverage for this:
The two instances in standard.install are defaults for shortcuts, because we don't support the rest through the UI yet, but Wim is about to open an issue for this.
Comment #10
xjmComment #11
xjmUpdated the summary to try to clarify the purpose of the scheme.
Comment #12
xjmComment #13
xjmComment #14
berdirIsn't changing this... problematic? We either need to do it before the upgrade path or provide update functions for it?
Comment #15
effulgentsia commentedRe #14, the issue summary says this is timeboxed to the next beta. But also adding the "D8 upgrade path" tag for extra clarity.
Comment #16
berdir@effulgentsia: Thanks, did not see that.
I'm quite confused now, because I really thought that I wrote a comment below already a few minutes ago, wondering if I posted that into a wrong issue somewhere ;)
My personal opinion is to stick with user-path, unless we are really convinced that we have a considerably better name than user-path, which would solve DX problems that we would have with user-path.
Many contrib modules track HEAD, not beta versions (Testbot can't target beta releases, for one reason), I've already updated a considerable amount of contribs to use base:, user-path: and so on over the weekend, as I'm using them for my project. Also, code would be relatively easy to fix, just a search and replace, but I'd rather not break existing installations unless we have a good reason to do so.
Comment #17
cafuego commentedMy first thought was 'node/add' has nothing to do with users, why would that exist on their profile? It's confusing and shouldn't be.
Comment #18
catchWhat about 'stored-path'?
Comment #19
effulgentsia commentedSome thoughts:
path,relative, or any combination that contains only those words or their synonyms, because those words have specific meanings already defined in RFC 3986. As a scheme name, they tell you nothing. A path to what? Relative to what? The purpose of a scheme name is to help answer those questions, so basing a scheme name on those words is highly circular.basetounroutedand then renaminguser-pathtorouted. That proposal was prior to us deciding to makeuser-pathhave the logic of checking for a route first, then falling back to a non-route, so this proposal would need to be updated to renameuser-pathtomaybe-routed, which I think is a bit icky, so -1.user-pathis that it doesn't handle (in terms of accuracy of the name) the use cases #5 and #6 from the issue summary of #2405551: Add a method to support UIs where users enter paths instead of route names and other valid use cases. David_Rothstein has argued that these use cases should be treated as legitimate, while pwolanin has argued they should not be.site. I think that is the most accurate semantics, because the namebasewas chosen to correspond to the definition of "base URI", which the specification requires to be independent of the path that follows. However, "site" is not defined by that specification, and IMO would just imply "something that is on this site", for which our current logic ofuser-pathis fully suitable. Additionally, I also think of "base" as connoting a meaning of "depends only on where Drupal is installed" and "site" as connoting a meaning of "depends on the site's configuration", both of those connotations being accurate aspects of the corresponding schemes.siteis a decent name. I know pwolanin wanted the name to make very clear that it should only be used when dealing with user input, but I also respect David's perspective in #2405551-70: Add a method to support UIs where users enter paths instead of route names and other valid use cases that we don't always need to embed the proper use case of something into its name.Comment #20
xjmHmm, #19 for me doesn't cover the most important thing about the scheme, which is that it's for user input only. I disagree with proposals that allow it for non-user-input. I also don't really agree with point 5. I can't imagine seeing
site:and understanding or remembering how it's different frombase:. It doesn't tell me that it could be routed, unrouted, tokenized, unsanitized, garbage...Comment #21
xjmWith the current direction of #2417459: Provide internal API for special schemes and thin public wrappers for user input and non-routed URLs, I could see
fromUserCreatedPath()orfromRawInputPath()or something like that. With method names, we lose the issue of verbosity and can be clearer about the purpose of the scheme, and avoid the confusion about paths to or for users. The scheme string itself becomes less critical.Edit: I'm still a fan of
user-input:for the scheme itself as it's the most explicit.Comment #22
effulgentsia commentedIf the decision gets made to keep the scheme name having the word
userin it, then some suggestions to address #17:-
user-input-
user-entered-
user-provided-
user-specifiedNot sure if those are improvements at all, or even if they are, if they're sufficient improvements to overcome #16. A problem with those first two is that what we store might not be exactly what the user typed. For example, maybe the user started with a leading slash, but we store without the leading slash. Even if we end up doing #2417647: Add leading slash to paths within 'user-path:' URIs, to allow 'user-path:' URIs to point to the <none> route, maybe some other widget will want to come along and not require users to enter a leading slash. I don't think we should change our storage model every time we want to change UX, so we should assume that some level of normalization can happen on input.
If we keep
user-SOMETHINGin the name, then we may want a separate scheme for the few use cases like an install profile installing an initial value that could then be edited by the user. Since technically, those initial values themselves are not input, entered, provided, or specified by the user. But that's a solvable problem that we can discuss further in #2416843: Decide if a Url::fromPath() method and/or a Url::fromUri() scheme other than 'base' or 'user-path' is wanted to support contrib/custom modules.Comment #23
catchThis is why I suggested 'stored'. The main thing that distinguishes this is that it's stored (in either configuration or content entities usually). When we're using it for shortcuts, 99.9% of the time the user isn't actually entering a path in a form at all either.
Comment #24
xjmAs far as I understand, shortcut is an interim state. At least, that's what I've heard several times from those working on it.
Comment #25
webchickGiven the next beta is February 25, a week prior to that seems like a good deadline for this discussion, to give us enough time to roll/re-roll a patch (if applicable).
Also adding "Needs issue summary update" because I don't think any of the discussion has been captured there yet.
Comment #26
webchickIf #2417459: Provide internal API for special schemes and thin public wrappers for user input and non-routed URLs ends up happening (which it appears there is growing support for), I wonder how important it is that we retain the "user" part of this scheme name, given that it is our sincere hope that 99% of developers will never deal in writing these schemes out manually, in favour of using the method wrappers (which would have "user" in the name).
That would open back up options such as
path:orrelative:or some other straight-forward, plain-English description, since the primary reason to change this scheme name is the confusion it's causing people due to the fact that it's used for more than just user-input.Comment #27
effulgentsia commentedI wouldn't characterize it as confusion, but disagreement. There are some people arguing that it should ONLY be used for user input, and others wanting the same functionality available for non-user-input.
#23's suggestion of 'stored' is interesting, in that it covers things that are stored in config or content, but that might have been set by code (e.g., an install profile or Shortcut's star icon). But I also wonder if we should store those cases with a different scheme, such as
route:for the case of Shortcut's star icon.Comment #28
catch@effulgentsia I don't think it matters whether something in config or content was created by actual user input or via the API (or between shortcuts star icon and the shortcut admin form) - the end result is going to be the same. If I saw a different scheme I'd expect it to be treated differently rather than an alias.
Comment #29
effulgentsia commentedI've been thinking about
storedas a scheme name, and although it might be 99% accurate (its main use case is for internal links, defined by path, that need to be stored, and as a result, whether it's routed or not, and if so, which route it resolves to, can change between when it's written and when it's read), it just doesn't feel right to me. I'm open to it if others like it, but on a gut level, I'm not crazy about it.I tried to rethink what the
baseanduser-pathschemes represent, and whether it's possible to find names for both that reuse common terminology for how people think about links.I think that the most important aspect of the
basescheme is that it will return a $url whoseisExternal() = FALSEandisRouted() = FALSE. And I think the most important aspect of theuser-pathscheme is that it will return a $url whoseisExternal() = FALSEand whoseisRouted()might be either TRUE or FALSE.With that in mind, what if we rename
basetounroutedand renameuser-pathtointernal?So per #27, I think this is the fundamental disagreement in this issue. I think what's most important about the scheme is that it's for links to something that is internal to the site but may or may not be handled by Drupal (e.g.,
/blogcan be a Drupal route or a subfolder in which Wordpress is installed, but in either case it's still part of the same website). And that user input is perhaps the only legitimate use case for such links, but that's secondary. However, I also understand the perspective that the user inputtedness of it is very important and that importance needs to be reflected somehow. Would this desire be sufficiently addressed by #2417459: Provide internal API for special schemes and thin public wrappers for user input and non-routed URLs's addition of aUrl::fromUserInput()method, even if what the method did was create a $url whose URI is in theinternalscheme?Ok, so with the above proposal, code that deals with user input can call
Url::fromUserInput(), and code like an install profile that creates path-based menu/shortcut links can write out'uri' => 'internal:/node/add'directly (or use a constant for 'internal'), so as not to call fromUserInput() on something that isn't user input.Comment #30
webchickI like
internal:quite a lot, and I think theUrl::fromUserInput()in the public API helps people do the right behaviour.unrouted:sounds like technical gobbeldygook, but at least is much more clear exactly what it means thanbase. Though I still would prefer to merge these and some smart code behind the scenes do$this->isRouted = $this->isThisARoute($path);to determine what $isRouted should be set to programmatically versus having a human have to do the distinction. Because once again to a "lay person" both /README.txt and /node/add are "internal" links.Comment #31
wim leersFunny… in trying to think of simplifications for the "many methods" problems at #2417459: Provide internal API for special schemes and thin public wrappers for user input and non-routed URLs, I thought:
In that light, this proposal makes a lot of sense to me.
entity:is a special kind (a subset) of internal link, which is also semantically/logically consistent with aninternal:URI scheme.It's also wholly consistent with Drupal's long-standing need for "internal links" that keep working after migrating from dev to staging. I've long wanted to add a text format filter that transforms internal URIs to resolved URLs. Seeing
<a href="internal:/contact">Contact us</a> to hear more!orRead more <a href="entity:taxonomy_term/5">about llamas</a>in there is completely natural.Finally,
user-path:stresses the fact that it's a user-entered path… which is true, but OTOH any such URI has actually already gone through validation. So the danger we associate with "user input OMG OMG" actually is no longer there; the validation has already taken care of that. Which is another point in favor ofinternal:IMO, especially together with aUrl::fromUserInput()method (or, if my proposal to simplify theUrl::from*()land is applied, perhaps evenInternalUrl::fromUserInput()).EDIT: I've always favored
unrouted:overbase:for its absolute clarity and its conveying of exactly what it is. It's others that need to be convinced.Comment #32
webchickUpdating the issue summary to reflect current convergence, and also to remove the list of ones we're not going to do (curious people can just read the issue).
Comment #33
webchickAnd a more focused title.
Comment #34
webchickAlso, effulgentsia pointed out that
user-path:/internal:already works in the way I described in #30, so in that case, spun out #2422995: Remove the base: scheme in favour of user-path:/internal:.Comment #35
xjmI think
internal:/fromUserInput()also makes sense. I'll split that bit out from #2417459: Provide internal API for special schemes and thin public wrappers for user input and non-routed URLs and post a starting patch here.Comment #36
xjmInitial patch. Renames the scheme, adds
fromUserInput, and adds the internal constant. I'll post a few notes with Dreditor in a subsequent comment.Comment #37
xjmShould we change the expectation for the destination parameter to always include a leading slash? (Would be a followup.)
Will add tests for this once I see what happens with the patch itself.
We should probably move some of the (lengthy) docs for this to the public method, but for now I've just replaced the scheme name.
In addition to the @todo, feels like we shold not be doing this string replace here. Additionally, shouldn't the path be displayed with the leading slash, in order to be aligned with the expectations set in #2417647: Add leading slash to paths within 'user-path:' URIs, to allow 'user-path:' URIs to point to the <none> route and for the user interface? Would be a followup.
I think we could add an API method for this check; it happens in several places.
We might want to look into refactoring this method. Maybe this is going to be fixed up in #2418017: Implement autocomplete UI for the link widget?
This helper function also implies that something maybe should be refactored (in a followup).
Note: In tests, I've deliberately used the hardcoded string, rather than the constant. This is not an inconsistency; it probably makes sense to hardcode things in related tests to ensure we're testing the right things. That said, I didn't closely examine each test to see what was appropriate in each case.
Do we have that issue for fixing shortcut somewhere?
Views should probably expect and display leading slashes as well (in a followup).
Comment #38
wim leersIf it's just for the scheme checking: PHP already provides an API for it (
parse_url()), which is what we choose to use. No need to abstract this away. At least, that's what effulgentsia, pwolanin and I thought at the NJ sprint.What do you mean?
Comment #40
xjmSeveral times, we've stated that shortcut is in an interim state where it doesn't support all the things, and that's why it has (edit!)
user-path:all over it. However, I can't find the issue that's supposed to fix it.Comment #41
xjmMigrate oopsie... (I still don't get those being config entities btw.)
Looking into the other fails.
Comment #44
xjmShould fix the fails (I think).
Comment #46
xjmComment #48
xjmOne more.
Comment #49
xjm...upload failure. DrupalCon wifi--
Comment #50
tim.plunkettwellchange back towe'llOtherwise, I think this patch is great.
Comment #52
xjmNeeds update for #2409209: Replace all _url() calls beside the one in _l() now. The Drop is always moving, etc.
lol... I guess PHPstorm tried to "fix" my quote delimitation? We shouldn't be using contractions anyway.
Comment #53
xjmComment #54
xjmWait a second, I didn't even make any changes to the line in #50... overhelpful IDE--.
Not bothering to revert the out-of-scope line for now.
Comment #55
xjmOh right.
Comment #56
dawehnerI'm sorry but I still think that internal has less semantic than user-path had.
IMHO its a bad assumption to not use user-path because "it went through validation", ... we talk about an API function here, there is noone assuring that every user
string went through validation, nor does it make sense to change the behaviour after validation.
Comment #57
effulgentsia commentedAnd related comment from #2422995-19: Remove the base: scheme in favour of user-path:/internal::
I understand the above sentiment, especially since in Drupal we have a history of saying "internal path" to mean "a Drupal-controlled path", but I think our history of using language that is inconsistent with the rest of the world should not count against us moving towards semantics that are consistent with the rest of the world.
If you have your Drupal installation in http://example.com, and a Wordpress installation in http://example.com/blog, then regardless of whether a user types "/blog" or whether an install profile does an
entity_create('menu_link_content', array(..., 'uri' => 'SOME_SCHEME_NAME:/blog')), then I think it is simply incorrect for anyone to think that that is not an "internal" link. The "internal" vs. "external" terminology for links/URLs is entirely about "internal to the website", not about which piece of software processes the request. Drupal's history of equating "internal" to "internal to Drupal" is an artifact of its history of being monolithic, but elsewhere throughout Drupal 8, we've gotten off the island, and we should apply the same spirit here.However, while a user typing "/blog" can be rightly classified as a "user path", an install profile doing the above entity creation can't be (IMO), so therefore, I think
internalis more semantically correct and clear thanuser-path, once you make the jump to not thinking that Drupal is the only piece of software that is "internal" to your website.Comment #58
xjmI broke this (it will throw an exception) but nothing failed. Fixed that bug in the attached patch but did not try to add test coverage (brrrr, views.theme.inc).
Also added the tests, fixed some test naming/docs, and fixed that silly apostrophe thing.
Comment #60
xjmSo good you get it twice.
Comment #61
xjmFrom my perspective, the reason not to call it user-path is that it's not a path to or for a user.
Comment #62
xjmComment #63
wim leersI really don't know what this refers to. Shortcut now uses the link field and link widget. In terms of being able to store links, I really don't know what's missing.
I think there's a simple justification in this case: the install profile creates this link on behalf of the user.
Comment #64
tim.plunkettI think that every name we pick is going to have some confusion inherent in it.
At this point, I think all that we can do is pick the least confusing name, the one that needs the least explaining.
Because once the intention is explained, you don't need to relearn it each time.
So let's focus on the most easily understood name.
Comment #65
effulgentsia commentedReroll + some manual conflict resolution
Comment #66
effulgentsia commentedRemoved the constant. Let's defer that to #2417459: Provide internal API for special schemes and thin public wrappers for user input and non-routed URLs.
Comment #67
effulgentsia commentedLet's keep in mind that wherever code is dealing directly with user input, it can call Url::fromUserInput(). So, the attached patch is just the hunks that do not do that, and instead deal with the scheme name directly. I think these are the hunks we should evaluate with respect to which scheme name is most understandable. I also omitted the
Urlclass itself, since APIs should be evaluated based on how callers are impacted rather than how the implementation is impacted.Comment #68
xjmIf we are changing all these lines anyway, it's not clear to me why we would split this into separate issues and change them again. I'd rather re-scope this issue to deal with internal (as we have) and deal with base: etc. there (as we already are).
Comment #69
effulgentsia commentedJust a reroll.
Comment #70
effulgentsia commentedMaybe what's best to do here is baby steps. In order to separate where we are dealing with actual user input from other usages of the scheme, I opened #2426181: Add a Url::fromUserInput() wrapper method for generating URLs from user-entered paths as a child issue. Maybe let's work on getting that in first? Then we can discuss the remaining hunks here with less noise.
Comment #71
effulgentsia commentedOk, so what I'd like to point out about all the hunks in #67 is that they're all dealing with the 'uri' value of a link field. Because all of HEAD's other usages of the 'user-path' scheme can use the Url::fromUserInput() wrapper method that's in #2426181: Add a Url::fromUserInput() wrapper method for generating URLs from user-entered paths. But what's left in #67 is where we need to work with a URI string rather than a $url object, and at least so far in HEAD, the only place we do that is the link field.
And when it comes to the link field, we already have a
LinkItemInterface::LINK_INTERNALconstant and aLinkItem::fieldSettingsForm()implementation that exposes the terminology "internal links" and "external links" to the UI for configuring that field.So, I think naming the scheme "internal" wouldn't require much explanation: it means the same thing as what the link field already means in the above.
Comment #72
wim leersWhat do we need here to move forward again?
Comment #73
mpdonadioThe patch needs a reroll. I'll do it shortly.
However, I think the argument in #71 is good, especially the parallel to the terminology in the link field, and that moving forward with 'internal:' is a good idea.
Comment #74
mpdonadioMinor manual merge in the docblock for Url::fromInternalUri() b/c of a change from #2423579: Url::fromUrl('user-path:/') should throw an exception when a path component without a slash is given.
Comment #76
mpdonadioForgot to update a test that got added. Passes locally now.
Comment #77
hussainwebI am wondering that with the scheme as
internal:, won't it make more sense to call the method asfromInternal()orfromInternalPath()? I see the method is introduced here (or in #2426181: Add a Url::fromUserInput() wrapper method for generating URLs from user-entered paths) and we could reconsider renaming it as we are also renaminguser-path.I re-read the comment in #29 and think that as
internalmakes more sense thanuser-path,fromInternalPath()also could give more clarity thanfromUserInput().Also, I see that parts of this patch are also in #2426181-11: Add a Url::fromUserInput() wrapper method for generating URLs from user-entered paths. Should this be postponed until then? (I know this deadline is today).
Comment #78
effulgentsia commentedI completely rewrote the summary. Hope it's helpful. Feel free to edit if not.
I don't think so. The point of the method is to only use it for user input, and to be clear that that's its only purpose. Whereas the more generic scheme name is to also cover the cases when it's not user input. In the future, fromUserInput() might do more than just be a wrapper around the generic scheme. For example, maybe it will perform additional validation or set a special key in $options to maintain a flag that it's from user input.
I think it makes sense to not commit this issue until after that one. But I think it's good to keep the status of this as not postponed, because discussion and reviews of the non-overlapping parts can be happening in parallel.
According to #25, today's deadline was just to reach a decision, and that we still have a few more days to get the patch to RTBC and committed.
Comment #79
effulgentsia commentedFixed an example in the summary.
Comment #80
hussainwebI just caught a few more references to
user-path:and changed it tointernal:.Comment #81
xjmThanks @hussainweb! We should change those method names too. EDIT: That is, change the names of test methods that test the user-path scheme to not be testFooUserPathBar(). However, I think it would make sense to only roll this patch on top of #2426181: Add a Url::fromUserInput() wrapper method for generating URLs from user-entered paths (which I am updating now). I'll reroll this on top of that once that's posted.
Comment #82
xjmRerolled on top of #2426181: Add a Url::fromUserInput() wrapper method for generating URLs from user-entered paths. The
-do-not-test.patchincludes only the changes that aren't included there. The interdiff, similarly, includes changes that aren't included there. Renamed the relevant test methods, a few missed things, etc., and reverted a couple out-of-scope changes and use statements that were no longer needed.Comment #83
xjmRerolled again for #2426181: Add a Url::fromUserInput() wrapper method for generating URLs from user-entered paths. All changes are from that issue.
Comment #84
xjmBeta eval. Also presumably there's a CR out there somewhere that would need an update.
Comment #85
xjmOne of these days I will fill out the template without leaving a
-->in.Comment #86
xjmComment #87
xjmfromUserInput()is in now. No additional instances ofgrep -r "user-path"norgrep -ri "userpath", except for the one inPathBasedBreadcrumbBuilderTestthat is actually a about path to a user, not an internal URI. ;)NR!
Comment #88
xjmhttps://www.drupal.org/node/2417421 somehow never got published, but that's the one we'll want to update for this. Added it here.
Comment #89
xjmHm actually, that change record never got finished -- some of the info on it is incorrect. But that's out of scope here.
Comment #90
effulgentsia commentedPatch looks great to me. Just does what the issue title says, so RTBC. Committers: please let this sit at RTBC for 24 hours or so to give anyone who might still disagree with this issue a chance to say so.
I think we'll want to change this doc, but that can be a followup, because it'll probably take us some time to come to consensus on what it should say.
Comment #91
xjm@effulgentsia, yeah I forgot to mention, but there's a lot of docs work that needs to be done at some point that is out of scope here. #2417459: Provide internal API for special schemes and thin public wrappers for user input and non-routed URLs includes a bunch of work in that area, though it's possible we might want to split the scope there, too.
Comment #92
mpdonadioAre there any in-progress issues/patches that introduce new user-path: usages that will need to be rerolled after this?
Comment #93
xjmComment #94
xjm@mpdonadio, probably a number of things in the queue will need rerolls, but nothing outstanding from #2407505: [meta] Finalize the menu links (and other user-entered paths) system to my knowledge. #2417459: Provide internal API for special schemes and thin public wrappers for user input and non-routed URLs is stale now, but in the good way.
Comment #95
alexpottCommitting in the last minute before the beta release freeze so this is in the next beta. Committed 368cf51 and pushed to 8.0.x. Thanks!
Thanks for adding the beta evaluation to the issue summary.
Comment #97
pwolanin commentedI'm sad to see this go in - I think "internal:" is totally misleading.
Comment #98
dawehnerWhat peter says. For me
internal:motivates people to not useroute:, even if they would know it.User-path had more semanticness for me.