change hook_user('view') so that they return fapi style arrays and then render through drupal_render. this is exactly analogous to the recent change to nodes.

- modules may now build fields using a well documented model. no more funky $category stuff
- modules may alter the profile fields of other modules using same technique as nodes. here, we use hook_user('alter'). module developers rejoice.
- deprecates the hook_profile_alter() that i submitted to core a couple weeks ago :)
- i added user_profile.tpl.php file and a bit of logic in phptemplate.engine to use that file. themers rejoice.
- i moved the theme('user_picture') out of theme_user_profile() and into user_view() since it belongs in the structured array.

i will update docs one this gets in. requires a change to Contrib modules that implement hook_user('view')

Comments

moshe weitzman’s picture

StatusFileSize
new7.68 KB

a real file

eaton’s picture

This, friends, is where it is at. We have a badass rendering infrastructure and places like this are perfect for it. Will have more opportunity to test tomorrow, but a HUGE +1 to the principle.

dries’s picture

Not tested yet but +1 on the idea.

walkah’s picture

big fat juicy +1 for the idea. I just quickly tested it, and it looks like something might be up : I added 2 textfield profile fields, but only one is getting displayed on user view. I'll try and have a more in depth look later.

nothing jumps out looking at the patch itself.

dries’s picture

James promised to give this a decent review.

drewish’s picture

StatusFileSize
new7.74 KB

i fixed a bug in user_profile that was causing it to only display a single field.

drewish’s picture

err, profile_view_profile() rather.

in comparison to the old formatting, i think the fieldsets look pretty tacky. i'd much rather use headings than fieldsets.

drewish’s picture

StatusFileSize
new8.59 KB

chx alerted me to the fact that i didn't include a file.

moshe weitzman’s picture

thanks for the fix, drewish. perhaps someone can come up with some CSS that looks better than plain fieldsets. i do think fieldsets are semantically correct and consistent with rest of drupal. i'm not so excited to add custom markup for this. more opinions are welcome.

webchick’s picture

Status: Needs review » Needs work

user/1 is just giving me a blank page with this patch. Trying to track it down...

webchick’s picture

Additional: When I submit the user edit form I get:

    * warning: _phptemplate_render(./themes/engines/phptemplate/user_profile.tpl.php): failed to open stream: No such file or directory in /Applications/MAMP/htdocs/head/themes/engines/phptemplate/phptemplate.engine on line 398.
    * warning: _phptemplate_render(): Failed opening './themes/engines/phptemplate/user_profile.tpl.php' for inclusion (include_path='.:/Applications/MAMP/bin/php4/lib/php') in /Applications/MAMP/htdocs/head/themes/engines/phptemplate/phptemplate.engine on line 398.

Which Ted tells me is because a file is missing from the patch, so I will wait for his re-roll and then review. :)

m3avrck’s picture

StatusFileSize
new8.52 KB

Updated patch to fix those problems webchick was encountering.

However, there is a larger problem. The output *should* not be using fieldsets whatsoever, those are for form elements. Heck, the HTML looks like:

<fieldset><legend>Personal</legend><div class="form-item">
 <label>Last name: </label>
 Serbinski
</div>
<div class="form-item">
 <label>Name: </label>
 Ted
</div>
</fieldset>

That's not a form!!!

I looked into this and I don't think it's a problem with this patch, but a larger one in general. The output should ideally be: each category as an DL, with an H3 for a title and DT / DD for each of the values.

However, I don't see any possible way to do this because it's passing things to drupal_render() ... perhaps that needs to be patched for when content is being viewed?

If that is case, then don't hold up this patch, it's ready to go. We'll march on over to drupal_render() to fix that so those in the know speak up :-)

eaton’s picture

drupal_render() is utterly and completely agnostic about the content it renders. If you set #type on each element to 'profile_field' it will call theme_profile_field when it comes time to render them. If you set the #type on the enclosing element to profile_category, it will call theme_profile_category...

m3avrck’s picture

StatusFileSize
new9.95 KB

Eaton you're right, here's a patch that introduces a new theme_dl() ... after talking with Moshe and Karoly, this is our best bet.

m3avrck’s picture

StatusFileSize
new10.73 KB

Updated patch after talking with Moshe. New default CSS for better profiles :-)

m3avrck’s picture

StatusFileSize
new12.04 KB

Screenshot of CSS.

moshe weitzman’s picture

Status: Needs work » Reviewed & tested by the community

great work, ted. now any rendering hierarchy can be output as DL

seems to work. the category bug initially reported is fixed. i say this is rtbc.

dries’s picture

Status: Reviewed & tested by the community » Needs work
  • Please remove 'user_build_content()'. There is only one call to this function.
  • Why are definition lists the best solution? Personally, I don't see profile elements as definition lists. I think of these are regular key-value pairs, rather than term-definidation pairs.
  • Crazy idea: generate microformat enabled profile (http://microformats.org/wiki/hcard-examples) -- probably not for this patch. ;-) Note that the hcard examples in the link above are not using definitition lists either.
moshe weitzman’s picture

user_build_content() mirrors node_build_content(). i think it is a useful pattern to emulate. further, i am already using node_build_content() in og.module. just because core doesn't use user_build_content() doesn't mean that it won't be used anywhere. i propose that we leave this function in.

i will let someone else answer the DL question.

yeah, we really should do the microformats thing in a subsequent patch. i don't see an example there of a collection of categorized lists.

chx’s picture

Status: Needs work » Reviewed & tested by the community

DL is easily answered, that's how it's done now. See http://api.drupal.org/api/HEAD/function/theme_user_profile . If you do not like the DLs, that's another issue, this patch just moves things towards a better modell.

And Moshe answered the other two. So, putting back to RTBC.

m3avrck’s picture

As for DL, have a read.

Some people believe that definition lists should only be used for terms and definitions. Others believe that definition lists can be used to tie together any items that have a direct relationship with each other (name/value sets). This second point of view is supported by an example within the W3C specifications

Because the W3C says so ;-)

dries’s picture

OK. Next issue: I find it very difficult to figure out whether all the data has been properly escaped.

For example, in theme_dl():

+  $output = ($element['#title'] != '') ? '<h3>'. $element['#title'] .'</h3>' : '';

Is $element['#title'] secure? It all looks insecure ...

chx’s picture

Dries, compare please theme_dl and theme_user_profile. Zero escape and it should be so. Also observe the following untouched code in profile module:

if ($value = profile_view_field($user, $field)) {
       $description = ($field->visibility == PROFILE_PRIVATE) ? t('The content of this field is private and only visible to yourself.') : '';
       $title = ($field->type != 'checkbox') ? check_plain($field->title) : NULL;

The title is escaped for good in there. And profile_view_field gives a treat to various types -- textareas are check_markup'd and so on. I can not see any new secholes blown by this patch.

drumm’s picture

Status: Reviewed & tested by the community » Needs work

First of all, dl is good.

- The visual theming looks really heavy, grey, and arbitrary. It should be as little as possible and anything fancy needs to be done by bluemarine and friends.
- As node.module exemplifies, #type => markup is unneeded.
- What is a #type => item? theme_item() calls theme_form_element(), which is certainly wrong for user viewing.
- Doesn't #type => dl need an entry in system_elements()?

This should be two separate patches. One to introduce theme_dl() and replace the hard coding we have scattered around now and a second for the whole content thing.

eaton’s picture

- Doesn't #type => dl need an entry in system_elements()?

Nope. system_elements() is necessary to provide default values for array properties that aren't specified, and other conveniences, but by itself, #type maps to theme functions.

chx’s picture

Status: Needs work » Reviewed & tested by the community

Drumm, this simply goes a bit far . Many, many patches in the past introduced new functions as they needed them without being split up. I do not see the reason to do such fine grain patches. These do belong together. It would simply delay development to say "to test this patch please first apply 79221 and then this one".

chx’s picture

Also, #type => item does call form_element but as we theme the whole stuff it does not matter, drupal_render does not reach this. Consistency reasons are behind the decision to be them items.

drumm’s picture

Status: Reviewed & tested by the community » Needs review

What consistency reasons?

moshe weitzman’s picture

StatusFileSize
new9.19 KB

Rerolled to remove use of #type=markup. good catch.

IMO, it is out of scope to discuss the implementation of #type=item here. it is a form element offerred by core, and renders exactly what is desired here. If type=item needs refactoring, then let's file a separate bug. an analogy: we do not stop patch 'foo' because it uses 'callback arguments' because the implementation of callback arguments needs improving.

i grepped the code and nothing uses DL in a place where drupal_render() is in effect. if it did, i would convert it here. if there is code in core that is using other sematics, when it should be using dl, then please file a bug. nothing about this patch makes it easier to use DL than it was before.

as mentioned by chx, it is a bit awkward to break this into 2 patches. one depends on the other. how can i intropuce theme_dl() without any users of it? i'm all for small patches when they don't create dependencies.

ted is about to resubmit with new css as suggested.

m3avrck’s picture

StatusFileSize
new10.6 KB

Here's an updated patch. Also includes the user_profile.tpl.php that Moshe forgot ;-)

I changed the CSS back to something extremely simple. Neil that was a good point.

For those that are interested, with this setup, it makes it *really* easy to do some awesome stuff, like show profiles in a column view, with labels on left and values on right, very cool. But nothing fancy for the super simple Drupal themes :-(

m3avrck’s picture

StatusFileSize
new11.89 KB

Here's a screen of that simplicity.

chx’s picture

Status: Needs review » Reviewed & tested by the community

Drumm, as said, it could be any #type because drupal_render won't even reach that element, we render the children by hand in theme_dl. Consistency: something which is plain text but has a #title is an #item. That's it.

dries’s picture

m3avrck: are you saying that using form_alter() is easier than overwriting a theme function? IMO, this patch makes it harder to theme stuff. The current theme function also makes it easy to create two columns.

drumm’s picture

Status: Reviewed & tested by the community » Needs work

There are a few places we use dl in core. node/add and admin/help come to mind. I'd like to see these use a themable definition list function at some point and could be used to demonstrate a theme_dl() patch which stands on its own.

Lets compare theme_dl() to its nearest relative, theme_item_list():
- theme_item_list() has a name which describes what it does- it is a themable list of items. theme_dl() is named after an HTML tag.
- theme_item_list() takes a list of items, which follows the 'foo' or array('data' => 'foo', ...) pattern. theme_dl() follows the #-means-metadata pattern.
- both attempt to explain complex array structures without an example.

If the # pattern is really what we want to use, instead of the 'data' pattern, I think throwing an example in the function documentation will help make that clear.

I'm not sure if I like the first new name that comes to mind, theme_definition_list(). The name 'definition list' is misleading, as shown above, and 'item list' doesn't directly correspond to ul or ol. The concept is a list of labeled items.

Why even set '#type' => 'item' if theme_dl() handles it and doesn't even look at #type?

The visual design looks good.

moshe weitzman’s picture

Status: Needs work » Reviewed & tested by the community

Dries - in order to achieve the themeing you suggest, you just create a function theme_
. If one already existed for the given form, you override by registering a #theme callback.

The bigger benefit here is for module developers who can now add/remove/validate etc. using a well known model.

@drumm - node/add and admin/help cannot use our theme_dl() because they don't use drupal_render() ... i have a scratch to itch, and that is to move profiles to use drupal_render(). my scratch is not to fix admin/help so it uses the render model, nor node/add. thats a big undertaking, with almost no benefit. don't hold up this patch because my code wants to output a DL.

so, what is it that needs doing here? i can't see a todo coming from the last 2 comments. i set this to RTBC. feel free to move back to needs work with some todo items.

dries’s picture

Moshe: I know how to theme. The point is that with the proposed system, it takes one extra step (i.e. a form_alter), and one that is not necessarly designer friendly. I was just objecting to Ted's comment which suggested that this would make theming easier. Quite the opposite, I'd say.

I agree with Neil that the theme_dl is quite different from theme_item_list -- someone a designer would not expect, IMO.

m3avrck’s picture

@Dries, I say it's easier to theme because it follows CSS Zen conventions--output the correct HTML and let CSS take care of you.

In this case, the output is a DL. So what you might think, right?

Well, actually, that is completely wrong. Make my DL into a table, how about a calendar, image gallery-esque, and boxtastic

That's pretty darn easy to theme, have a look for more examples: http://www.maxdesign.com.au/presentation/definition/

If Drupal outputted *consistent* and clean HTML *everywhere*, we would have no real need for theming functions, IMO :-)

But, to play devil's advocate, yes if you don't want this to be a DL or need something else, you'll need to create a theme_() and work a bit of form_alter(). But then again, you have a user_profile.tpl.php to play with as well. And that has the $account array which has *everything* a themer would need to use:

  stdClass Object
(
    [uid] => 1
    [name] => ted
    [pass] => 49e02178d15a1784c2e98a5335824b83
    [mail] => ted@lullabot.com
    [mode] => 0
    [sort] => 0
    [threshold] => 0
    [theme] => 
    [signature] => 
    [created] => 1156297548
    [access] => 1156521406
    [login] => 1156521368
    [status] => 1
    [timezone] => 0
    [language] => 
    [picture] => 
    [init] => ted@lullabot.com
    [data] => a:2:{s:6:"submit";s:18:"Create new account";s:7:"form_id";s:13:"user_register";}
    [submit] => Create new account
    [form_id] => user_register
    [roles] => Array
        (
            [2] => authenticated user
        )

    [profile_name] => Ted
    [profile_last] => Serbinski
    [content] => <dl class="user-member"><dt>Member for</dt><dd>2 days 14 hours</dd></dl><h3>Personal</h3><dl><dt class="profile-profile_last">Last name</dt><dd class="profile-profile_last">Serbinski</dd><dt class="profile-profile_name">Name</dt><dd class="profile-profile_name">Ted</dd></dl>

    [profile] => Array
        (
            [summary] => Array
                (
                    [member_for] => Array
                        (
                            [#value] => 2 days 14 hours
                            [#title] => Member for
                            [#type] => item
                            [#printed] => 1
                        )

                    [user_picture] => Array
                        (
                            [#value] => 
                            [#printed] => 1
                        )

                    [#weight] => -5
                    [#attributes] => Array
                        (
                            [class] => user-member
                        )

                    [#type] => dl
                    [#children] => <div class="form-item">
 <label>Member for: </label>
 2 days 14 hours
</div>

                    [#printed] => 1
                )

            [Personal] => Array
                (
                    [profile_last] => Array
                        (
                            [#attributes] => Array
                                (
                                    [class] => profile-profile_last
                                )

                            [#weight] => 0
                            [#value] => Serbinski
                            [#title] => Last name
                            [#type] => item
                            [#printed] => 1
                        )

                    [profile_name] => Array
                        (
                            [#attributes] => Array
                                (
                                    [class] => profile-profile_name
                                )

                            [#weight] => 0
                            [#value] => Ted
                            [#title] => Name
                            [#type] => item
                            [#printed] => 1
                        )

                    [#title] => Personal
                    [#type] => dl
                    [#children] => <div class="form-item">
 <label>Last name: </label>
 Serbinski

</div>
<div class="form-item">
 <label>Name: </label>
 Ted
</div>

                    [#printed] => 1
                )

            [#children] => <dl class="user-member"><dt>Member for</dt><dd>2 days 14 hours</dd></dl><h3>Personal</h3><dl><dt class="profile-profile_last">Last name</dt><dd class="profile-profile_last">Serbinski</dd><dt class="profile-profile_name">Name</dt><dd class="profile-profile_name">Ted</dd></dl>

            [#printed] => 1
        )

)

I can use all of the #title/#value pairs to do whatever I want if need be.

So yes, easier to theme IMO.

drumm’s picture

Status: Reviewed & tested by the community » Needs work

theme_dl() is still misnamed and underdocumented. See my last review for details.

chx’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new8.87 KB

If theme_dl holds up this important patch then fuck it. Now it's theme_profile_category.

chx’s picture

StatusFileSize
new8.88 KB

Moved theme_profile_category to user.module. That this function should be theme_dl and reusable as such? Noone cares it seems. Then me neither.

dries’s picture

Dries, compare please theme_dl and theme_user_profile. Zero escape and it should be so.

That doesn't help me. Where is $category escaped, for example? (Categories can be created through the administration page.) Maybe the old code was buggy too?

Bèr Kessels’s picture

http://drupal.org/node/54898 there is a more general theme_definition_list.

chx’s picture

StatusFileSize
new8.89 KB

So, now we do not trust user administrators to not enter XSS? What's the point? But again, I am happy to jump over whatever.

dries’s picture

We're discussing this on the mailing list.

drumm’s picture

Status: Reviewed & tested by the community » Needs work

I'm still not sure why we have the useless #type=>item in some places. It is confusing because it is never actually used for anything.

I'd love to see a good theme_dl() in core, but it does not have to come with this patch (I'd prefer a patch before this so this can use it, but I can't be picky about the order of patches).

This is a good improvement since the elements of content are always at the same array positions (they are assigned sequentially now). But the double use of it, building ->content and then at the last minute switching to ->profile and overwriting ->content is confusing.

This does seem consistent with how nodes do it.

moshe weitzman’s picture

Status: Needs work » Reviewed & tested by the community

@drumm - it seems like you set this back to needs work because of the usage of 'item'. what resolution do you want to see with this? these can't be #type=value since that element ignores the #title attribute. personally, i think it is out of scope to reengineer form api. this patch doesn't touch form.inc.

as you suggest, it makes little sense to reengineer node building with this patch. i try to maintain consistency.

drumm’s picture

Status: Reviewed & tested by the community » Needs work

From my previous review:

"I'm still not sure why we have the useless #type=>item in some places. It is confusing because it is never actually used for anything."

Why not just omit is since theme_profile_category doesn't seem to look at it. I'm not asking for things to be reengineered. The #type is never used so why confuse people by saying there is a form item there?

"But the double use of it, building ->content and then at the last minute switching to ->profile and overwriting ->content is confusing."

Nothing was said about that.

chx’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new8.88 KB

#type item is now #type profile_item and thus the theme profile_category got simplified seriously. there is no ->profile any more. otherwise patch unchanged from the previous RTBC stage.

chx’s picture

Credit goes to Ber for the generic idea of how theme_profile_item should look like.

chx’s picture

StatusFileSize
new8.74 KB

Apparently I have no uploaded the file I intented to.

chx’s picture

StatusFileSize
new8.95 KB

*sigh* Steven will kill me for posting in rapid succession but returning and rereading the whole issue dawned on me we lost a tpl.php along the way.

moshe weitzman’s picture

nice work ber, chx, drumm. this is an even cleaner patch.

i tested all looks well.

m3avrck’s picture

Excellent work guys! Code is cleaner and we still have our semantic DL and such. I'm happy with the new patch even if my theme_dl is gone ;-)

Good to go indeed!

drumm’s picture

Status: Reviewed & tested by the community » Needs work

Looking good.

We have this useful structured array of $account->content which is overwritten by a string right before we theme it. Wouldn't it be good to be able to access that array from the themable function?

The css probably needs to be in user.css. It isn't included if you have profile module turned off, which is the default.

moshe weitzman’s picture

Status: Needs work » Needs review
StatusFileSize
new9.25 KB

moved styles from profile.css to user.css

reinstated the use of $account->profile so that theme function gets a structured array in addition to the string. as drumm pointed out earlier, this is a bit tricky but i don't see a better solution, considering that we want hook_user implementors to be acting upon $account->content since thats what nodes do. i prefer that implementors of the hook be shielded from all inconsistency.

drumm’s picture

Status: Needs review » Needs work

.profile h3 is in profile.css while I'm 90% sure that h3 comes from user module.

moshe weitzman’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new9.26 KB

oops. moved that css class. no outsanding review issues so i move to RTBC. feel free to change status if needed.

Egon Bianchet’s picture

Version: x.y.z » 6.x-dev
Status: Reviewed & tested by the community » Needs review

Resurrecting and putting to "code needs review" since it's been a while ...

bdragon’s picture

subscribing

webchick’s picture

Status: Needs review » Needs work

No longer applies.

moshe weitzman’s picture

Status: Needs work » Closed (duplicate)

reborn at http://drupal.org/node/144397. please review.