I'm using and loving DS for a project I'm working on right now, but have run into a problem with the way the field markup is being rendered. I'm not actually positive whether this is a bug or a feature request, but here's the deal....

I have a field.tpl.php in my theme, along with a preprocess function that's used as a the default for most of my fields. When I check "Enable field templates" all hell breaks loose, and my template is no longer used for any field whether there are any "field display" settings or not.

I think this is a bug because looking at theme_ds_field() and the 'ft-default' variable, which on my end is 'theme_field', it seems like it should actually be using my template. After noticing this, I tried using a theme function as opposed to a template file in my theme. That didn't work, so I pasted my modifications directly into core's theme_field() and as soon as I did that, it DID end up using that, which means I'd have to hack core to provide a default.

I would expect that the "Default" option would allow me to use my own theme's field.tpl.php, not core's theme_field() because I have overridden it. So, I'm wondering can this be fixed, or if it's being done on purpose or something?

CommentFileSizeAuthor
#13 1265920.patch9.09 KBswentel
#9 1265920.patch7.58 KBswentel

Comments

mortendk’s picture

+1 super subscribe hear hear

swentel’s picture

I've always wondered when this would come up :)

So what's happening behind the scenes when enabling field templates is this:

  • In the theme registry, I change the theme field function to theme_ds_field
  • theme('field') now calls theme_ds_field as the default field theming function
  • Inside that function, I call theme_field() (the default original) directly (in case that's the default one or nothing is configured), instead of theme('field') - because that would otherwhise cause infinite loops and crash Drupal

So, that's most likely the reason preprocess functions and/or templates aren't found anymore because it's not going through the theme() function anymore. theme_field__field_type() functions however should work, but that's not interesting if you would like to have your own default one. The 'Remove theme suggestions' on the 'Field templates' configuration form is actually a way to kill all those suggestions because bartik for instance declares bartik_field__taxonomy_term_reference() which takes precedence over theme_ds_field and some people don't want (it beats me as well why they're using bartik as their frontend end theme, but that's another discussion ;p )

However, there is a way do declare your own (theme) function for fields. You can implement a hook called 'hook_ds_field_theme_functions_info' and define your own theme field functions, and through the interface at admin/structure/ds/extras you can select that one as the default function. You can add more and select those per field in the interface afterwards as well.

I'm not entirely sure if this hook gets picked up in the backend in case you declare that hook in template.php of your frontend theme, but in a module file it most certainly will.

function hook_ds_field_theme_functions_info() {
  return array(
    'my_own_default_theme_function' => t('My awesome theme field function'),
    'another_cool_field_function' => t('Another cool field function'),
  );
}

After that, the keys of that array are the actual function names. The function gets 2 parameters: $variables and $config. Config holds some configuration options you can set on the UI (most probably the label, extra classes, however, not stuff you can enter when using the expert mode).

function my_own_default_theme_function($variables, $config) {
  return 'My default field output here';
}

function another_cool_field_function($variables, $config) {
  return 'My other default field output here';

}

So, the way we work is that we indeed have our own default theming field function declared in that hook for most fields and 2 more. Sometimes we use the expert mode for real edge cases per project.

Is it a bug ? Well, in a way it is, because it's ignoring Drupal's internal way of working, on the other hand, I feel like it's a feature. Now, because front end people are my main audience, I certainly want to investigate if I can still make the original field.tpl.php work - although as I've pointed out in the beginning, there's a reason I call theme_field() directly, but it's worth investigating once more. Maybe there's an option to instead of using field.tpl.php, ds comes with ds-field.tpl.php and that one becomes the main preprocess function/template file, not sure.

However, in case you guys say, wow, that hook is freaking cool and we'll use that one, that's even better. Let me know :)

mortendk’s picture

okay this is all good n cool ... but (yes you knew it was coming)

this looks like its only usable in a module, and it would be pretty sweet to have it in the theme instead ;) so we dont end up having a theme support module ;)

jacine’s picture

Ugh, damn Tao for hiding the form element descriptions. I see now that this is mentioned there in the UI. Sorry about that. Thanks for the awesome explanation @swentel! I had a feeling there was a good reason. ;)

Preprocess and theme_field__field_type() implementations do work, regardless of the theming hook used which is sort of odd. The end result is like a half-ass manipulation because some of the stuff is started in preprocess and then not followed through in the final theme hook. I found this to be really confusing. I completely understand your issue with the more specific theme implementations and having to deal with that in DS, but I still think that DS should not mess with actual defaults.

I tried implementing the hook you provided in a theme and it doesn't work. :(

What if instead of doing the logic for this in theme_ds_field() you used hook_preprocess_field() and added theme hook suggestions? In there you could probably check for DS field display configuration, and then tack on more suggestions only if configuration settings have been set. Something like this:

function ds_preprocess_field(&$vars, $hook) {
  $element = $vars['element'];

  if ($ds_configuration_settings_exist) {
    $ds_suggestions = array(
      'field__ds',
      'field__ds__' . $element['#field_type'],
      'field__ds__' . $element['#bundle'],
      'field__ds__' . $element['#field_name'] . '__' . $element['#bundle'],
    );
    $vars['theme_hook_suggestions'] = array_merge($vars['theme_hook_suggestions'], $ds_suggestions);
  }
}

This would give the following results, and make DS functions outweigh all the core suggestions, while allowing to still target specific templates. And since the preprocess functions work regardless, it seems like it could work.

Array (
     [0] => field__text_with_summary
     [1] => field__body
     [2] => field__event
     [3] => field__body__event
     [4] => field__ds
     [5] => field__ds__text_with_summary
     [6] => field__ds__event
     [7] => field__ds__body__event
   )
mortendk’s picture

wheres the google +1 button for #4 ?

swentel’s picture

Oh my god! That's a freaking good idea!
I'll start experimenting with this. The awesome thing is, this probably won't break existing sites out there. Hope to get a patch this weekend!

jacine’s picture

Sweet! Thanks so much @swentel! :)

Regarding breaking existing sites, I'm not positive how DS works right now. Does field--whatever.tpl.php override anything set in the field display settings right now? It appears that it does and if that's the case, then with the method suggested in #4, theme_field__ds() would win over field--whatever.tpl.php, and that would break existing sites. This would mean:

  1. If the theme_field__ds() implementation is not wanted, the field settings settings would need to be removed in the UI.
  2. Or in the theme, if DS field display settings exist and field--whatever.tpl.php exists, it would need to be renamed field--ds--whatever.tpl.php.

If this is a problem, you could also decide to just let field-whatever.tpl.php win, by sticking the field__ds suggestion right in the beginning of the array. As long as the theme hook suggestion is added conditionally based on whether configuration options exist, it would still allow the theme's default to be used. This might actually make more sense, because people shouldn't really expect to have it both ways.

jacine’s picture

Err, sorry, I was getting a little ahead of myself. The last paragraph would not solve the problem of overriding the Bartik example. I'll strike that. But the part above that, regarding breaking sites still applies.

swentel’s picture

StatusFileSize
new7.58 KB

It's easier than I though it would be. Patch attached keeps all my tests running which is great. So what changes with this patch:

  • ds_extras_theme() defines theme_ds_field_reset and theme_ds_field_export. The theming functions are a bit weird and long, but this way, existing sites won't break.
  • Instead of taking over the theme_field function, ds_preprocess_field() is now finding out whether there is some configuration and adds either 'theme_ds_field_reset' or 'theme_ds_field_export' as a theme suggestion. I also think that only one is enough as they are quite specific theming functions already.
  • The 'kill theme suggestions' option has been removed, it's redundant now

Score!

I think now Drupal's way of theming is preserved and it should find your field template. Additional configuration from ds is available in $variables['config'] - although the label or extra classes are changed/added already in ds_preprocess_field() as well.

I'm going to test with this some more over the weekend, but if you guys could try this out and let me know how this goes and add feedback, that would be really great.

jacine’s picture

AWESOME! I was just about to commit workaround code for this, but now I can test instead. Yay! :D

I will report back with test results soon, thank you!!

jacine’s picture

Status: Active » Reviewed & tested by the community

This is working well on my end! I've got a default field.tpl.php, a field-addressfield.tpl.php and a combination of fields that have DS settings and that don't, and it's all good with the patch.

In short, YAY! Thank you :D

swentel’s picture

Status: Reviewed & tested by the community » Needs work

wuuw cool :)

The patch needs work though on my end, but it's not a biggy. I need to modify the ds_extras_theme() to register my ds field theming functions and use the 'function' key. This way, any site out there that uses the hook_ds_field_theme_functions_info() is not going to break (we are using this on a couple of sites already and it breaks because that function isn't registered in the hook_theme()

Hope that makes sense, it shouldn't change the functionality as it works now for you guys. Anyway, in short, this

function ds_extras_theme() {
  return array(
    'theme_ds_field_reset' => array(
      'render element' => 'element',
    ),
    'theme_ds_field_expert' => array(
      'render element' => 'element',
    ),
  );
}

will change to something like this

function ds_extras_theme() {
  $theme_functions = array();
  $ds_field_functions = module_invoke_all('ds_field_theme_functions_info');
  foreach ($ds_field_functions as $key => $label) {
    $ds_field_functions[$key] = array(
      'render element' => 'element',
      'function' => $key,
    );
  }
}

No time for the patch now, will post back this weekend. But I'm already glad this is working out fine!

swentel’s picture

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

Update patch - ds_extras_theme() registers functions in hook_theme(). Should't affect existing functionality (you'll need a cache clear probably)

swentel’s picture

Status: Needs review » Fixed

Committed this, still works fine and has extras tests as well. wuuuu!

jacine’s picture

Status: Fixed » Needs review

Hey, sorry I was so late to get back to this. I just tested it and it's not actually working. My theme's field.tpl.php doesn't get used. I was running 7.x-1.3 with the previous patch applied and it worked perfectly. After applying the patch in #13, my theme's field.tpl.php was no longer used. When that didn't work, I figured maybe I needed the dev version, so tried with 7.x-1.x-dev, but that didn't work either. I also got some errors on update:

Strict warning: Declaration of [error]
views_plugin_ds_entity_view::options_validate() should be compatible
with that of views_plugin_row::options_validate() in
_registry_check_code() (line 2702 of
../.includes/bootstrap.inc).
Strict warning: Declaration of [error]
views_plugin_ds_entity_view::options_submit() should be compatible
with that of views_plugin_row::options_submit() in
_registry_check_code() (line 2702 of
.../includes/bootstrap.inc).

Not sure why, or if those errors are related, but I'm going to revert to the previous patch for now.

swentel’s picture

Hrm, that's weird, it works fine on my end.

I have a field.tpl.php and a field--image.tpl.php in my bartik templates folder and they are used. If I override a field with say the 'reset' or 'expert' option, that function is used instead, so not sure what's going wrong, especially since the differences in that patch are really small.

Those errors aren't related normally, but I'll fix them however, always annoying.

swentel’s picture

Note, the strict warnings are gone in dev as well.

swentel’s picture

Status: Needs review » Fixed

Did more tests and seems to be working fine, please reopen if the problem persists - maybe with some clear steps to reproduce, since I can't at this moment :)

jacine’s picture

Ok, I understand. I don't know where it breaks down, but it definitely wasn't working. I don't really have clear steps. I just applied the patch, ran updates, cleared the cache, and my theme's template wasn't used anymore (see #11 for the setup). I'll try it again soon with a fresh install.

Thanks again @swentel :)

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

pascalduez’s picture

When updating from 7.x-1.3 to 7.x-1.x-dev I get some warning message:
Warning: Missing argument 2 for theme_whatever_field() [...]
I know it has been updated on the api file comments, but maybe should be precised on the doc or a more "accessible" location.

Custom theme field functions now only take one parameter ($variables) in place of ($variables, $config).
So to go back on the aforementioned example in #2 :

function hook_ds_field_theme_functions_info() {
  return array(
    'my_own_default_theme_function' => t('My awesome theme field function'),
  );
}

function my_own_default_theme_function($variables) {
  return 'My default field output here';
}
atlea’s picture

I'm not sure if this patch is in the latest dev, but I made this work by changing the template suggestion order in my THEME_preprocess_field function. Seems like theme_field should be a fallback function.

If I was to patch DS to do the same, I would change:

  // Determine the field function. In case it's something different
  // than theme_field, we'll add that function as a suggestion.
  if (isset($config['func'])) {
    $variables['ds-config'] = $config;
    $variables['theme_hook_suggestions'][] = $config['func'];
  }

into:

  // Determine the field function. In case it's something different
  // than theme_field, we'll add that function as a suggestion.
  if (isset($config['func'])) {
    $variables['ds-config'] = $config;
    $variables['theme_hook_suggestions'] = array_merge(array($config['func']), $variables['theme_hook_suggestions']);
  }

in ds_extras.module.

atlea’s picture

My bad, this is only an issue if the site default is not set to "default" and the field is changed separately to "Default".. so this would be better:

  // Determine the field function. In case it's something different
  // than theme_field, we'll add that function as a suggestion.
  if (isset($config['func'])) {
    if ($config['func'] != 'theme_field') {
      $variables['ds-config'] = $config;
      $variables['theme_hook_suggestions'][] = $config['func'];
    }
  }
  else {
    $field_theme_function = variable_get('ft-default', 'theme_field');
    if ($field_theme_function != 'theme_field') {
      $variables['ds-config'] = $config;
      $variables['theme_hook_suggestions'][] = $field_theme_function;
    }
  }

The extra check "if ($config['func'] != 'theme_field') {" was added. It would be great, however, to have extra theme suggestions when using eg. minimal as site default.

donquixote’s picture

Status: Closed (fixed) » Needs work

This is still broken:
If I choose "Minimal" as the default in ds extras settings, then there is no way to let a specific field render as "Default".
We need to separate "Use theme_field" from "Use default setting in ds_extras".

Taxoman’s picture

Version: 7.x-1.3 » 7.x-1.x-dev
jonmcl’s picture

swentel’s picture

Status: Needs work » Closed (duplicate)

Yes, I think the patch over there is having the right fix, so let's move over there. I've asked my frontend people at work to test it and report back to me as soon as possible. If ok, I'll backport it to the 7.x branch as well.

swentel’s picture

Issue summary: View changes

typo