Problem/Motivation
The properties of user objects (returned by user_load(), stored in the global $user, etc.) are not documented anywhere.
Proposed resolution
Create a doc group "user" and document the properties in its @defgroup.
Remaining tasks
- @defgroup text needs to be written. Initial patch in #20
- Decide where the @defgroup should go (currently: user.api.php, but might be better somewhere else?)
- Tag relevant functions. Much of what is in user.module qualifies, but others might, as well. Might happen in a follow-up patch.
- Link new group page from relevant places, e.g. global $user doc (this might happen via an @ingroup tag, if those also apply to variables?
- Backport patch to D7, making sure that nothing has changed since then (unlikely)
- Decide if patch should be backported to D6. If so, make sure that nothing has changed since then (more likely).
Original report by Lenn-art
Just an issue about the documentation. Doc says "Stores preferences and other user information", but which preferences? Where can i found more info?
print $user->name; gives me the name for example. Is there more? Like ->role or ->logintime?
Comments
Comment #1
jhodgdonThis is at http://api.drupal.org/api/global/user/6 (same in Drupal 7 as well).
Actually, a lot of the global doc headers are pretty vague. And they are in the contrib repository (why are they still in contrib for Drupal 7, by the way?) in developer/globals.php
Anyway, I agree that the doc for $user could be expanded to give more information.
Comment #2
MatthijsG commentedThe $user is one of the few that has some extra info 'in it'. Is there a way to print the whole array (i think, this is an array?)?
Comment #3
jhodgdonIf you want to do that for debugging, try the PHP print_r() function.
http://us3.php.net/manual/en/function.print-r.php
Comment #4
MatthijsG commentedOnly to see which options $user has.
I don't see how i get print_r working, because i need to set the array first.
- edit http://drupal.org/node/46200 suggested
to see all globals. But i want only them from $user. Not quite sure what i can do with this.
Comment #5
jhodgdonI'm not sure exactly what you are trying to do... But these questions look like they belong in the Support Forums, not the issue queue. Or you can ask on an IRC channel -- check out the Support tab on drupal.org.
Thanks for filing the doc issue, anyway, so we can put more details into the doc for $user.
Comment #6
livingegg commentedThis same nuisance has also been addressed in this post.
Comment #7
mr.baileysAdded example values similar to the documentation for the $language global.
Comment #8
jhodgdonThanks, this is a good start...
But generally in Drupal API documentation, instead of an example, we want to document what the components are rather than just giving examples. I'm not sure what the other variables in the globals file are doing, but that is generally the standard for Drupal. I think in this case that while some of the components of $user might be obvious, others are not, and they need descriptions.
Also, the standard is that the doc header should begin with one line of 80 characters or less, with a single sentence description. Not:
Comment #9
jerrac commentedSo, would something like this work? Note, I have no idea if what I am writing is correct. I'm just guessing at what the drupal core $user values are.
So, could someone update the http://api.drupal.org/api/drupal/developer--globals.php/global/user/7 page to give us that kind of information? It should also mention what differences there are when the user is not logged in.
Comment #10
jhodgdonThis isn't ready for a patch yet. If someone wants to create a list of what the $user components actually are, without spelling errors and typos, I can add it to the page. But I can't add it in its current format.
Comment #11
joachim commentedBTW: I think there's a real case for a hook_entity_schema, where modules define and describe all the properties they add into nodes / users / terms / etc.
Comment #12
jhodgdonThat would be great joachim, and then the API module could automatically build the "what's in the $user object" page.
Comment #13
Aragorn450 commentedThis seems to have died, but it's still an issue. So how about these definitions (taken from http://api.drupal.org/api/drupal/developer--globals.php/global/user/7#comment-17024 and cleaned up a bit)
From the 'users' Table:
From the 'sessions' Table:
From the 'user_roles' Table:
Comment #14
jhodgdonThat's a good start -- needs to be written as a patch, conforming to our docs standards (http://drupal.org/node/1354)
I'm moving this over to the Documentation project, which is where the globals file is located now.
Comment #15
sven.lauer commentedI was about to start to roll a patch based on #13, but then I thought that it might not be wise to put this in globals.php: After all, was this is about is what user objects look like in general---so really this should go into the doc of a user-related function (user_load()?) or into a "User" topic page. Then it could be linked from globals.php.
And +1 on the idea of a hook_entity_schema[_alter]()---not only could the API module use this, one could also imagine a devel module that shows all the current properties of an entity type (including those injected by contrib modules). And this would make it really easy to provide default tokens for all the properties of a user/node/etc.
Comment #16
jhodgdonOK, feel free to move this back into core and figure out where it should be documented then. thanks!
Comment #17
sven.lauer commentedMoving back to core queue.
Proposal: We create a gropu for User-related things, and describe the properties of user objects in its @defgroup.
Comment #18
sven.lauer commentedI updated the summary, to make clear what the issue is about by now. Also changing the title.
Comment #19
jhodgdonThat proposal sounds reasonable... a patch would probably clarify?
Comment #20
sven.lauer commentedHere is a first patch. Leaving at "needs work" for now, as I want to improve some of the property descriptions first. However, if someone wants to weigh in on missing properties in the mean time ...
Here is how I came up with/verified the list of properties:
- Started with the list in #13.
- Cross-checked with current 8.x user_schema().
- Cross-checked with current entity module's user.info.inc
- Finally, did a fresh 8.x install, enabled all optional core modules (and devel) and inspected the global $user with dpm().
Actually, none of the steps after the first one added any properties, but verified that they are there (and should be).
Comment #21
sven.lauer commentedAdding the backport tag.
Comment #21.0
sven.lauer commentedProper issue summary.
Comment #22
sven.lauer commentedUpdated issue summary with a couple of more things to be done / next steps.
Comment #22.0
sven.lauer commentedAdded some more "Next steps" to the issue summary.
Comment #23
jhodgdonI took a look at the current patch... Mostly looks good! A few things I would suggest changing:
a) I think we can leave out this one-sentence paragraph:
+ * Drupal provides user handling functionality, including user registration,
+ * and login, as well as integration with session and permission handling.
+ *
b) And maybe this one should be tacked onto the end of the following paragraph:
+ * A user object representing the user that is currently logged in is available
+ * in the global variable $user.
c) This is missing the word "not":
... user entities do come in multiple bundles, ...
d) E-mail doesn't need to be capitalized here:
+ * - mail: The E-mail address of the user.
e)
- Tables - put {} around the table name.
- "contrib modules"... These could be contributed or custom modules. Maybe best to just say "by modules"?
f)
Um... second argument of second argument??
g)
Put this with the other time-related items?
h)
Missing . at end of line, and maybe should go with the other timestamp items?
i) List formatting (: not -):
+ * - session - The user's session data stored in the $_SESSION variable.
+ * - roles - An array of roles assigned to the user.
Comment #24
sven.lauer commentedThanks for the review!
I adopted the changes you suggested, and did some minor reworking of the rest.
I also started tagging some of the functions in the User module.
A couple of questions:
(a) Is user.api.php the right place to put the @defgroup? Some modules seem to do this, though I guess an argument could be made to have it in user.module instead.
(b) Is "User API" a good title?
(c) It has actually occurred to me (trying to decide whether role-related functionality should get @ingroup directives) that the properties of role objects does not seem to be documented anywhere, either (though these are very simple: Basically, it is just role ID, label, and weight). But we could add those and have the group title be something like "User and role objects" and the summary be "Functions handling user and role objects" or something of the kind?
(d) For now I have only tagged functions that are really user-handling functions---though a case could be made for many functions that either take user objects as parameters or return them.
Comment #25
jhodgdonHmmm... I think it could make sense to have a "User API" group, but this documentation is about properties on the user object, so maybe the group that documentation belongs in is specific to a "user properties API" or something like that, and only functions/hooks that are related to user properties should be included? Such as user_load(), hook_user_load(), etc. ??
A few other things:
a)
before "rather", the , should be a ;
b) When I got to this:
My first thought was "How would it do that?" And also we don't want to specifically say "contributed" modules, since that specifically means modules downloaded from drupal.org. And "inject" -- didn't like that much... So how about:
(modules may add additional properties by implementing hook_user_load() or ...)
[well, I don't know how modules do this so you should substitute the correct answer...]
c) List formatting:
d) Order of the properties:
+ * - init: The user's email address provided during initial registration.
==> put this with the other email address ones? And maybe it should say that it is only available during initial registration, since that is not explicitly stated (if it is true, which I think it must be??).
Comment #26
sven.lauer commentedFixing the issues you mention:
b) Yes, adding properties directly is done via hook_user_load()---but properties can also be added by attaching fields, either in a module or through the UI. Explaining this got a bit much for a parenthetical remark, though, so I moved this to a separate paragraph AFTER the list of properties.
d) No, "init" is a database column in the {users} table, and is always loaded. Which is weird (and also, the property could have a way better name), but that is how it is. I moved the description of the property so that it is after the other email property, though.
I think it is probably a good idea to make this a very specific group---but I would call it "Properties of user objects" or simply "User objects" instead of "User properties API"---though I don't really see that anything BUT user_load[_multiple]() and hook_user_load() would belong into this group.
Ideally, I think that any function that either takes a user object as a parameter or returns one should get either an @see to this group, or have a link in the param/return doc, like
Though this would not have to happen with this patch, necessarily.
Comment #27
sven.lauer commentedComment #28
jhodgdonNot sure I agree that "every function that takes a user object" needs this reference. I think the vast majority only use a couple of properties, and I don't really think they need to reference this list of properties. I'm actually not all that sure why we need it, but it's been asked for and I don't see a reason *not* to document it... if only to point out that there's a lot of cruft in the user object that should be probably removed...
Anyway, this group one-line description still says "functions that handle user login" etc. I don't think any of that is very related to user object properties? And again, I take issue with the choice of which functions/hooks have been added to this group. Let's stick to documenting the list of properties of $user, and only put the @ingroup on functions that really relate to this. Like not hook_user_delete, for instance?
Aside from that, this list of properties is looking pretty good... Oh, one thing I just noticed: "an array of roles" -- are they role IDs, or is it an associative array of role ID -> role name, or what?
Oh, this:
That's not accurate, I think? At least with nodes, the fields' values are not directly properties in the object. It's a lot more complex than that, and I would assume it would be the same for user objects?
Comment #29
sven.lauer commentedI do agree that, most of the time, only a very small subset of these are of interest, but even if all you care about is the user's login name, you'll have to know whether it is stored in $user->name, $user->login, $user->login_name, $user->loginname, or $user->user_name, &c. ... and there is no place this is documented right now. And once we start documenting the properties, we might as well be comprehensive (with the added benefit of making it likely that someone looks at this list and thinks "holy cow, we should clean this up").
Also, I guess what I was thinking (but, uhm, not saying) was that HOOKS that take user objects as parameters and FUNCTIONS that return those should get a reference to this (but not necessarily be part of the group)---for callers of user-returning functions and implementers of user-taking hooks are who needs to know what they are getting.
I had not changed anything about what was tagged / the name and description, as I thought we might need to discuss this more, but the attached patch has a concrete proposal. The only things tagged as @ingroup are the various user loading functions and hook_user_load(). I also turned the string "user object(s)" in the
@param of hooks and the @return of functions into a link to the new group, but if you think that is too much, I can remove those.
I also made the doc for the 'roles' property more explicit.
Finally, when I wrote
I thought that this is adequate, as it does not specify the format in which the values are held in these properties (which is a [language][delta][column] array, as with nodes). But I agree that this can easily be misunderstood, so I changed the wording and added a link to the field_language group (which is where the format of field-properties is explained).
Comment #30
sven.lauer commentedComment #31
jhodgdonThis is very close!
The link structure you used seems OK to me. I somewhat prefer "See the blah_blah topic for more information", but what you did is definitely more compact and gets the job done... The only thing is that it makes it a bit hard to read in the code:
user_objects user object is a bit difficult to parse...
I also think the philosophy regarding links/groups is OK... should user_save() be in the group too though?
I'll also comment that this seemed weird to me at first read:
The Field Language API group is only about multilingual aspects of fields, but you are right, that is where the array structure of fields on entities is described, so that is the right link.
Comment #32
sven.lauer commentedI added
user_save(), as this seems to make sense to me.I also agree that the current format is not terribly easy to read in the code, but I am not sure that
is that much easier to parse.
An alternative would be to revert to
but add an
Which would result in a link with the text "User objects" in the "See also" section.
Your call.
Comment #33
sven.lauer commentedP. S. I also agree that the fact that the (only) place the structure of field property arrays is documented is the field language API topic is a WTF ... maybe this would be a good follow-up issue, though? From a technical perspective, this information should probably be in the Field Attach API topic.
Comment #34
jhodgdonSorry for not reviewing this sooner... I've been pretty busy. Anyway, I just took a fresh look at this patch, and I think your links are fine.
I noticed a few remaining things:
a)
The line before a list should end in :
b)
uid -> user ID
c) Functions that I think maybe (??) should be in this user_objects group, that I don't think are included in this patch:
- user_external_load()
- user_uid_optional_load()
(it seems like if user_load() and user_load_multiple() are included, these ones should be too?)
Then I think this will be good to go - thanks for all your work on this issue!
Comment #35
sven.lauer commentedThanks for all your reviewing effort, here and elsewhere!
Here is a patch fixing these issues.
Comment #36
sven.lauer commentedComment #37
jhodgdonThis looks good, thanks!
Comment #38
webchickHm. I'm really torn about this....
- This documentation is awesome, and much-needed.
- The down side is that it's far-removed from the actual object in question, and will likely fall out of date with changes in core.
- It's new documentation that didn't exist in D7 and previous, and speaks to more of this same kind of documentation being added for other objects, such as blocks, nodes, etc. That implies D8-only, except...
- As catch pointed out in IRC, all of those objects are planned to be converted to REAL objects as part of #1346204: [meta] Drupal 8 Entity API improvements (specifically #1361228: Make the user entity a classed object), which would actually keep the documentation and the code together, making it both more useful (it's available to IDEs and the like), as well as far more likely to be kept up to date.
So... I'm not sure. I really don't want to mark this "won't fix." :( But it really seems like efforts to better-document these properties are best spent converting the objects to actual classes so they become "real" properties that can then themselves can be documented. That'd make this a D7-only patch, which I'm not crazy about because we'd be introducing inconsistency of one of these objects documented but not the rest. :(
Comments/thoughts? Tomatoes? :|
Comment #39
gddIn Dries' recent discussion about core dev process and the irc chat that happened alongside, there was a lot of talk about how people working on something that might be clobbered by an initiative should just keep working because the initiative (or any other core dev) may not get done. I think this should fall under that category, especially as the conversion of user objects to classed entities is going to be huge and I could totally see it not getting in (did anyone really think profile module would survive a year and a half before D7 release?) Shouldn't this be committed and if it becomes irrelevant then so be it?
As far as the maintenance headache goes, I don't see it being any worse than hook documentation in *.api.php, which is also physically removed from the code.
Comment #40
catchI don't see the user conversion as an 'initiative', it's essential follow-up from a recent patch, and right now it's blocking an 8.x release so it technically doesn't matter how long it takes. However I also don't like holding up patches on other ones that aren't close to done yet.
I'm really not sure about the @link stuff added here though, since once we do have users as classed entities, we ought to be able to just type hint all those functions with the interface if we want to reference the structure of the user object itself, and I'm not really sure it adds that much without it (since what's in a user object now is pretty arbitrary).
Comment #41
jhodgdonAnother thing to consider is that $node and $user/$account are probably the most commonly asked-about "What does the structure of this thing look like" objects for new Drupal programmers, and the most complicated. So I don't think having doc for $account and not for $block and other such structures is a terrible thing. This is one of the most-requested things to document, and I'd sure like to see it documented... as far as it being far from the code, since the code that produces it is scattered all around the place, I don't know where else to document it?
Comment #42
sven.lauer commentedHere is my thinking:
@webchick: I agree that it is bad that this is so far removed from the code that generates the user objects. The problem is that there isn't really a good place to put it (the only place I could think of would be in user.install---as it is the hook_schema()-implementation that largely governs what goes into user objects right now. But putting substantial documentation into .install files would be a very new thing to do.
I agree that this documentation will likely be superseded by the move to classed entities for D8, so maybe this really should be D7-only ... or at least, maybe we should not put the @links etc. in D8, but still include the docgroup, even if it is just a placeholder / pointing out how much cruft is in the user objects.
With respect to inconsistency, two things: (a) Is it really so bad to have the inconsistency of having docs missing for only some objects, rather than have them missing for all of them? and (b) I'd be happy to commit some time over the next few weeks rolling similar patches for other object types (nodes, at the very least, blocks, ...), as I've been frustrated before about the missing doc. I would not think of this as wasted effort, even if it only goes into D7, or gets removed from D8 later on---people will be developing for D7 for a long time, and they really could use this information. That said: Getting those patches ready, of course, needs more work than just me rolling them, and jhodgdon has already indicated (in #28) that she is not convinced that this documentation is useful---so maybe she would think of reviewing more patches for similar things as a waste of time.
@catch: Isn't the fact that what is in the user objects is rather arbitrary a good reason to document this? It may not be for D8, as (hopefully) user objects get cleaned up anyways, so the documentation will have to change at some point, but for D7, I think having this kind of information is rather useful.
Comment #43
jerrac commentedAs someone who needed this documentation months ago, and was rather amazed it didn't exist, most of the comments against this documentation make no sense.
I really don't care about D8 right now, it's years in the future. Why punish D7/6 users just because D8 will change?
Who cares if some objects are documented and some aren't? This is a community project, so documentation is always going to be inconsistent, heck, I've never seen anything with consistent documentation.
Also, a quick glance at #20 makes me wonder why it wasn't applied right then. It was good enough to give people a clue, instead of the absolute lack of even an idea of where to look. Basically, something is better than nothing. Heck, my horrid first try at coming up with something would be better than what it is like now.
So, I really hope this gets applied right away.
All that said, there may be some very good reasons why I'm wrong. If there are, I can't see them, and they should be explained better, or fixed, so that developers understand why they have to spend hours trying to figure out what's in $user or other objects.
Comment #44
webchickYeah, I think it can get applied to D7. We're currently waiting on feedback from catch's question about the D8 version tho.
Comment #45
jhodgdonMaybe catch can rephrase his objection -- I'm not sure what we need to change to get this acceptable for d8/7?
Comment #46
catchSo for Drupal 8, if we have a type hinted user argument to each function, then people should be able to go from the type hint directly to the interface docs and find out about properties that way. This means we'd need to go through and remove the explicit links later again. Also having that link against all functions that take an $account object means it sets an example for contrib to do the same thing (not that contrib is chasing Drupal 8, but if it was).
That'd make me hesitant about committing this to D8, considering people are currently hard at work on #1361228: Make the user entity a classed object, if it wasn't going to be applied to Drupal 7 too, because it'd be work that'd have to be very quickly undone.
However, if we can backport this, I'm find with committing it to Drupal 8, even if it only stays in there for a month or two - since we should keep Drupal 7 and Drupal 8 in sync as much as possible until they actually diverge.
I'm not sure if this clarifies, but either way since webchick indicated she'll commit it to D7, I'm moving it back to RTBC.
Comment #47
sunMy considerations and problems with this patch:
@defgroupfor every possible entity in Drupal sets a wrong example/standard. API documentation groups are supposed to group functions that belong to the same functional topic. A "description of a user object loaded from the database" is not a functional topic.A "User API" would be a functional topic. It would group all public API functions that developers should use to perform CRUD operations on user accounts and closely related things. And such an API group topic page could as well document user account properties. Regardless of what exactly we're going to do for this issue, this would be very beneficial to do on its own.
@link ... @endlinkor (partially/potentially bogus)@ingroupdirectives anywhere.Comment #48
webchickI can see the logic in that, but I think the helpfulness of this documentation outweighs the valid concerns that we're not ACTUALLY documenting the user object, only its default properties. Seriously, I can't tell you how many times this comes up in #drupal as a question, and how helpful this sort of docs would be to new developers, especially themers. Having something to link to would be awesome. Maybe if we moved this documentation up or near to the top of the User API @defgroup (or create one if it doesn't yet exist), that would be a way to combat that concern?
However, that @link ... @endlink concern has come up several times now, so I agree it should be dropped from the patch. If we no longer created a defgroup for the entity, that makes that easy.
Comment #49
sunMaybe I wasn't clear - yes, I think we should add this documentation.
I merely don't see why we need to introduce an entirely new and custom pattern for documenting what developers should expect inside a certain variable - if the variable happens to be loaded somewhere and pretty much all code uses that loader to generate it.
Especially if we want to apply this style of documentation to more - nodes, comments, taxonomy vocabularies, terms, menu links, node types, image styles, image effects, etc. pp. yadayada. I don't see the point in introducing dedicated API doc groups for every single variable that developers can load and save and may have to deal with.
Instead of that, document the variable once where it's normally loaded, and make other docs just simply reference that function.
I'm pretty sure we have some excellent examples for this somewhere in core, but wasn't able to locate one in a quick peek.
Additionally, in crafting a patch for what I mean, it became pretty clear that the suggested intermixing of object properties here led to a seriously bogus documentation on its own - which only testifies what I tried to say:
- The session properties do not exist for bare user accounts being loaded, but only for the currently logged in user.
- The global user is not a fully loaded user account (and should not be treated nor saved as such).
See attached patch.
Comment #50
sven.lauer commentedThe approach in #49 looks fine to me (as did, obviously, the original one---which would have a bit more easily discoverable, I thought).
However, do we still need to introduce a new @defgroup if we do things like that? The stuff specific to the global $user variable could/should arguably go to the documentation of the global variable (i.e. at http://api.drupal.org/api/drupal/developer--globals.php/global/user ---this documentation is in the docs git repository, so would need a separate patch).
Comment #51
sunglobal $useris not a fully loaded user account object, so any reference to http://api.drupal.org/api/drupal/developer--globals.php/global/user would be completely bogus in the first place.The patch in #49 introduces a new '@defgroup user' to allow us to document the non-obvious tidbits of the User API. But I've also added a serious amount of clarifications on the $user vs. $account drama in that very patch and @defgroup.
If you want to get really nitty-gritty, then a ultimately valid argument would be that the documented properties in that User API group do not belong to the User API - instead, they are the essence of Drupal's Session API - which doesn't seem to be documented anywhere yet.
It's important that we understand those details before attempting to document them. If you have any questions, feel free to raise them. We're happy to help!
But anyway, what matters to me is that we need a documentation pattern that is capable of supporting N amount of entities-or-not-but-in-any-way-objects-handled-via-CRUD-functions. I fail to see how a @defgroup [object] could reasonably work out at a higher/broader level.
Comment #52
sven.lauer commentedI think we largely agree---here is what I meant to say: In your patch in #49, you retained the introduction of the user group, but a large part of the intro text of this group is now concerned with special properties of the $user global (which should be documented!), so this part arguably does not belong into the user api group at all, but rather should be added to http://api.drupal.org/api/drupal/developer--globals.php/global/user :
So, I realize that the global $user is not a user object and special, but I think that WHAT this global $user is should be documented in this global's documentation.
And with that (and the default properties for user objects moved to the user_load() documentation, the intro text in the doc group reduces to:
But most of this is fairly entity-general stuff ("User the _load()-function to load objects", "Fields can be attached"). The only thing that does not generally apply to (fieldable) entities is the bit about there being only one bundle. So I think (if we move the documentation of the default properties to user_load()), we should NOT have a special User API group, as this would document an instantiation of a general pattern (entity APIs) rather than documenting the pattern.
Comment #53
jhodgdonComing back to this... I think the ideas in #52 are good. Can we have a new patch to see how they would work out in detail?
Comment #53.0
jhodgdonAdding missing comment #.
Comment #54
legolasboThis is actually a bad practice since using
global $useractually exposes you to potential security escalation bugs.In Drupal 7 user_uid_optional_load() should be used to get the current user.
In Drupal 8 this changed: global $user deprecated in favor of current_user service
Comment #55
jhodgdonYeah we shouldn't even do this for Drupal 8 now.
Comment #56
David_Rothstein commentedI think this is still relevant for Drupal 7. It's quite common to use the global $user object (rather than loading the whole thing via user_load()) for performance reasons.
Not to mention that the structure of the user object returned by user_load() doesn't seem to be documented anywhere either....