When I create a subtheme of zen_ninesixty, I get this error:

warning: in_array() [function.in-array]: Wrong datatype for second argument in /Users/david/Things/bus/projects/all/drupalbase/server_local_full/html/sites/all/themes/zen_ninesixty/template.php on line 194.

line 194 has this: else if (in_array($style, $sub)) {, so apparently there is a problem with $sub at some point in the foreach loop.

I'm trying to start simple, so my theme is only the .info file:

name        = Test Theme
description = Test theme, based on zen_ninesixty
core       = 6.x
base theme = zen_ninesixty

I've tried a few things, but none of this got rid of the error. (Cleared caches many times too.)

- added stylesheets[all][] = layout.css to the .info file
- copied function zen_ninesixty_css_reorder into a new template.php file, renaming to my theme
- copied function zen_ninesixty_preprocess_page into the same new template.php file, renaming to my theme, and changing this:
$vars['css_alt'] = zen_ninesixty_css_reorder($vars['css']);
to this:
$vars['css_alt'] = testtheme_css_reorder($vars['css']);

I confirmed that the updated template.php file was being executed, but I still received the same types of errors.

Is there anything else I should check? Is there a simple example of a subtheme of zen_ninesixty I can compare to?

Comments

onejam’s picture

This Zen sub theme not a base theme. I'm not sure if you can create another base theme of from a sub theme?

It's sounds odd to want to create a sub theme with this when this is already a sub theme. If you don't want it to be called zen_ninesixty, you could just change the theme name in all the files, then you'll have your own sub theme. But you'll still need the Zen theme as this is the base theme it relies on.

Thanks,

crea’s picture

Status: Active » Closed (won't fix)

It is not possible to make subtheme of subtheme. This is limitation of Drupal theme system.

nadavoid’s picture

Personally, I don't like to modify any downloaded theme. I prefer to create a subtheme, so that if you make any modification/improvements/bugfixes to the original, it's easy for me to receive them, instead of having to merge them into my modified copy.

It is possible and straightforward to make a subtheme of a subtheme, and even have many layers of subthemes. I found that this is documented. a sub-theme can declare another sub-theme as its base. There are no hard set limits to this. on http://drupal.org/node/171194. -- My subtheme of zen_ninesixty was working fine, except for this one error.

So according to how the theming system is documented, it should be possible to subtheme any theme without getting errors. And I have a little bit of sadness, not being able to subtheme zen_ninesixty.

crea’s picture

Status: Closed (won't fix) » Active

Well that is surprise for me, as documentation says subtheme subtheming is possible. Personally I prefer to avoid such configurations. And leaving zen_ninesixty as base theme doesn't add much value: basically it's only value is grid system, in other areas it's Zen. Also subtheming of subtheme would add additional unneeded overhead. Probably because of too much overhead there are not many people using multiple layers of subtheming.
In the meantime, feel free to submit patch for reordering function that will make it work in all cases.

niklp’s picture

I disagree, most of the "big hitters" in theming are overjoyed that the possibility to create these multiple layers exists now.

I'd refer you to the upcoming Paris Drupalcon and a particular session that I believe is included by MortenDK, probably entitled "mothership", a strategy for theming that invokes this exact method.

crea’s picture

Well, this can be workarounded by using zen_ninesixty as draft for your last theme in subtheme order, and making final them out of it. You will just need to change it's basetheme to your other theme which then will inherit Zen in some way. I'm not sure though, it may require some tweaking of reordering function too..
Besides that, I think noone will argue against using proper function that work in all cases. I made this reordering function quick and dirty way, and it's better than what we had before (not working function).

niklp’s picture

Hm well the whole point of subtheming is that you shouldn't have to alter anything that's higher up in the hierarchy. Altering the 960 subtheme means you can't install updates or improvements to the subtheme without using diff and manually patching things, including css, which is a total non-starter really.

This system is designed so that we can add updates instantly and use source control so we dont' have to worry about any of those other troublesome aspects...

onejam’s picture

I think we all agree there should be a way of creating a subtheme of a subtheme since Drupal allows for this.

But the issue here is the function to reorder the CSS which needs to be fixed and that function is important as we want the stylesheets for the framework to be included first. Will look into this.

@nadavoid what happens if you don't copy that function over to your template.php?

crea’s picture

Actually, it was programming error: before using array operations one must make sure he has array type of variable. So my new version of function inserts this check, and also magically it starts to work in all cases (atleast it worked for me in the test). It worked in zen_ninesixty only because the theme has css defined for every $media, and stopped to work in your subtheme cause you probably had css defined for some $media, not all of it.
Also I removed second global variable cause it's not used, and added some comments.

Step 1: remove any copied function from your subtheme of zen_ninesixty: all processing will be in zen_ninesixty itself;

Step 2: replace reordering function inside template.php of zen_ninesixty with the following:

function zen_ninesixty_css_reorder($css) {
  global $theme_info;
  
  // Rearrange css files based on their origin
  // Order is: framework > module > basetheme > subtheme
  foreach ($css as $media => $groups) {
    // Setup framework and subtheme groups.
    if (isset($css[$media])) {
      $css[$media] = array_merge(array('framework' => array()), $css[$media]);
      $css[$media]['subtheme'] = array();
    }
    else {
      $css[$media]['framework'] = array();
      $css[$media]['subtheme'] = array();
    }
    // Prepare subtheme css array to compare against.
    if (is_array($theme_info->info['stylesheets'][$media])) {
      $sub = $theme_info->info['stylesheets'][$media];
    }
    else {
      $sub = array();
    }
    // Loop over CSS files moving them to corresponding groups.
    foreach ($groups['theme'] as $style => $status) {
      if (strpos($style, 'framework') !== FALSE) {
        // This is framework style! Move to framework group
        $css[$media]['framework'][$style] = TRUE;
        unset($css[$media]['theme'][$style]);
      }
      else if (in_array($style, $sub)) {
        // This is subtheme style! Move to subtheme group
        $css[$media]['subtheme'][$style] = TRUE;
        unset($css[$media]['theme'][$style]);
      }
    }
  }
  return $css;
}
crea’s picture

Status: Active » Needs review

The only issue left with CSS is some modules still insert their css at the top of the list somehow: e.g. Views and Admin Menu. I'm not sure if this is important. But I guess this must be fixed separately, if it must be.

onejam’s picture

Thanks Crea. I don't think we should worry about stylesheets from other modules as long as styles.css or the main stylesheet is loaded after all the rest of the stylesheet files then users can use this to override any CSS.

@nadavoid - can you test this code in your sub-theme and confirm if it's ok.

vellines’s picture

It seems to be working correctly in mine.

crea’s picture

Title: PHP error when subtheming zen_ninesixty » Quest for Holy Grail of all reordering functions.

I found another bug with this function: because we setup our own groups which drupal_get_css() doesn't expect, removing unused css files in subtheme doesn't work, if missing css files are provided in info file. So I added merging of groups into single 'theme' group, cause all our styles are actually theme styles.
Also I removed subtheme group checking, cause it seems to work without it.
And because drupal_get_css() starts to function as it should, new order is: module > framework > basetheme > subtheme.
Please check this new function.

function zen_ninesixty_css_reorder($css) {
  global $theme_info;
  // Rearrange css files based on their origin
  // Order is: module > framework > basetheme > subtheme
  foreach ($css as $media => $groups) {
    // Setup framework group.
    if (isset($css[$media])) {
      $css[$media] = array_merge(array('framework' => array()), $css[$media]);
    }
    else {
      $css[$media]['framework'] = array();
    }
    // Loop over CSS files and move to framework group if needed.
    foreach ($groups['theme'] as $style => $status) {
      if (strpos($style, 'framework') !== FALSE) {
        // This is framework style! Move to framework group
        $css[$media]['framework'][$style] = TRUE;
        unset($css[$media]['theme'][$style]);
      }
    }
    // Merge 'framework' and 'theme' groups into single 'theme' 
    // group, as drupal_get_css() expects.
    $css[$media]['theme'] = array_merge($css[$media]['framework'], $css[$media]['theme']);
    unset($css[$media]['framework']);
  }
  return $css;
}
onejam’s picture

Thanks for the update.

I haven't yet got the time just now to test it but if someone can test and confirm it's working, i'll commit the changes and release an update theme later next week.

vellines’s picture

I've got the updated function working without problems: zen-ninesixty > base-theme > sub-theme in a mutisite setup where some sites use the sub-theme & others only use the base-theme. The css files seem to be ordered as crea has described.

crea’s picture

I removed construction which didn't make sense with foreach(). Please try new version :)

function zen_ninesixty_css_reorder($css) {
  global $theme_info;
  // Rearrange css files based on their origin
  // Order is: module > framework > basetheme > subtheme
  foreach ($css as $media => $groups) {
    $framework = array();
    // Loop over CSS files and move to framework group if needed.
    foreach ($groups['theme'] as $style => $status) {
      if (strpos($style, 'framework') !== FALSE) {
        // This is framework style! Move to framework group
        $framework[$style] = TRUE;
        unset($css[$media]['theme'][$style]);
      }
    }
    // Merge all 'framework' and 'theme' groups into single 'theme' 
    // group, as drupal_get_css() expects.
    $css[$media]['theme'] = array_merge($framework, $css[$media]['theme']);
  }
  return $css;
}
onejam’s picture

Thanks all. I'll have some time over the next couple of days to commit the changes.

onejam’s picture

Status: Needs review » Closed (fixed)