in #506836: Add ability to inherit Skinr styles from parent themes it suggests that you can add skinr[options][inherit_skins] = true to your .info file to have skin settings inherited from base theme. This doesn't appear to work in 7.x-2.x. Is there an equivalent?

Comments

moonray’s picture

Status: Active » Fixed

Inheritance from the parent theme should be automatic (the skin files get automatically included). It won't automatically enable the skins, though. You might have to add a hook_skinr_skin_info_alter() in your theme's *.skinr.inc file to change the skins' statuses to enabled (or disabled) for your sub-theme.

Example:

<?php
/**
 * Implements hook_skinr_skin_info_alter().
 */
function mytheme_skinr_skin_info_alter(&$groups) {
  // Enable skin.
  $skins['skin_name']['status']['my_sub_theme'] = 1;
}
>?
mrfelton’s picture

Status: Fixed » Active

All of the skins are already available to use in my base theme. It's the actual applied skin styles that are not being inherited.

For example, I set the default theme to my_base_theme, and configure a load of skinr styles for various elements on my site. I'm using the SwitchTheme module to allow users to switch the theme to one of several subthemes, where things like colours and background images are changed. When the theme is switched, none of the blocks etc have the skinr styles applied. I can edit them manually and add them for each specific subtheme - but I want them to inherit them automatically.

moonray’s picture

That's not within the scope of Skinr.
You can probably get the effect you're looking for by doing some magic in a custom module using hook_skinr_preprocess_alter()

mrfelton’s picture

Seems like a pretty common thing to want to do. In my experience Sub themes (I'm talking about theme variations - not base theme subthemes) would generally only override a small amount of styles. We have hundreds of skinr styles set on our main theme, and don't want to override any of these in the the various subthemes.

Why would that not be in the scope of Skinr? Sounds like a pretty useful option to have.

mrfelton’s picture

I have this semi-working in a custom module, however, there is a problem with Skinr that's stopping me from being able to do what I need to do. The code below works, but only for elements where at least one skinr attribute has been set on the subtheme. The problem seems to be that you only actually call skinr_preprocess_alter on elements that have some skinr properties set. That would generally make sense, but for this use case it doesn't as the active theme won't have any/many skinr settings on any elements.

/**
 * Implements hook_skinr_preprocess_alter().
 */
function alumni_base_skinr_preprocess_alter(&$skins, $context) {
  // Fix for update script.
  if ($context['hook'] == 'maintenance_page') {
    return;
  }

  $current_theme = skinr_current_theme();
  $themes = system_rebuild_theme_data();

  $skinr_settings = (array) $themes[$current_theme]->info['skinr'];

  // Inherit styles from theme parents, if inherit_styles set to true
  if (isset($skinr_settings['options']['inherit_styles']) && $skinr_settings['options']['inherit_styles']) {
    if ($parent_styles = alumni_base_skinr_inherited_styles($current_theme, $themes, $context)) {
      $skins = $parent_styles + $skins;
    }
  }
}

/**
 * Retrives all the Skinr skins from theme parents.  Theme skins 
 * will override any skins of the same name from its parents.
 */
function alumni_base_skinr_inherited_styles($theme, $themes, $context) {
  $base_theme = (!empty($themes[$theme]->info['base theme'])) ? $themes[$theme]->info['base theme'] : '';
  $skin_info = skinr_get_skin_info();
  
  // Get a list of skin configuration IDs to pass to
  // skinr_skin_load_multiple().
  $params = array(
    'theme' => $base_theme,
    'module' => $context['module'],
    'element' => $context['elements'],
    'status' => 1,
  );
  $sids = skinr_skin_get_sids($params);

  return skinr_skin_load_multiple($sids);
}
mrfelton’s picture

Status: Active » Needs review
StatusFileSize
new1.93 KB

I can't see a viable way to do this using the prepress_alter function. I can't really see a good reason why this would be out of scope in Skinr, so here is a patch that adds style inheritance support to Skinr, enabling the use of a skinr[options][inherit_styles] = true setting, which will allow applied styles to be inherited from the base theme.

moonray’s picture

skinr[options][inherit_skins] = true was used in Skinr 6.x-1.x and 6.x-2.x to do what I described above: make skins in the base theme available. Not to automatically apply skins from the base theme to the sub theme.

You can achieve your goals by duplicating loading the skins for your base theme in hook_skinr_preprocess_alter() and adding those to the $skins array.

Note, this code wasn't tested:

<?php

function mymodule_skinr_preprocess_alter(&$skins, $context) {
  if (isset($context['caller']) && $context['caller'] == __FUNCTION__) {
    // Prevent recursion.
    return;
  }
  $current_theme = $context['theme'];
  
  $extensions = skinr_implements_api();
  if (isset($extensions[$current_theme]['options']['inherit_styles']) && $extensions[$current_theme]['options']['inherit_styles'] && !empty($extensions[$current_theme]['base themes'])) {
    $inherit = TRUE;
  }
  
  // If inheritance is enabled, traverse up the theme inheritance tree
  // looking for skins.
  if (isset($inherit)) {
    $sids = array();
    foreach ($extensions[$current_theme]['base themes'] as $base_theme) {
      $params = array(
        'theme' => $base_theme,
        'module' => $module,
        'element' => $elements,
        'status' => 1,
      );
      if ($parent_sids = skinr_skin_get_sids($params)) {
        $sids += $parent_sids;
      }
      // If this base theme doesn't also use inheritence, then stop here.
      if (!isset($extensions[$base_theme]['options']['inherit_styles']) || !($extensions[$base_theme]['options']['inherit_styles'])) {
        break;
      }
    }
    if (empty($sids)) {
      // Noting to do.
      return;
    }
    
    $newskins = skinr_skin_load_multiple($sids);

    // Allow alter by additional modules.
    // Invoke hook_skinr_preprocess_alter() in all modules.
    $newcontext = clonoe($context);
    $context['caller'] = __FUNCTION__;
    drupal_alter('skinr_preprocess', $newskins, $newcontext);
    
    $skins += $newskins;
  }
}
?>
mrfelton’s picture

skinr[options][inherit_skins] = true was used for that - that's why I names this inherit_styles, as we are talking about inheriting applied styles, not defined skins. I haven't tested your code above, but it's a similar approach to what I was trying initially in preprocess. But, it wont work because preprocess only gets called for elements that have at least one style applied in the current theme.

moonray’s picture

Status: Needs review » Needs work

You're right about this approach not working.
Your other option is to duplicate the skinr_preprocessor function as mymodule_preprocess, and then add only the base module skin settings, and not the current theme's skin settings (which will be added by skinr_preprocess, still). Since it just adds classes to the classes_arrray it should be stackable.

Another option is to hijack skinr_preprocess by removing it from the list using hook_theme_registry_alter() and using you own version; this would prevent duplicate code from being run.

As for the option... this is excerpted from the Skinr docs (it's not about applied skins, but enabled skins):
Inheriting Skinr styles from a base theme
If you are creating a subtheme and the base theme you are using contains it's own Skinr styles, Skinr allows you to choose whether or not you want your subtheme to inherit those skins or not. By default Skinr will NOT inherit skins. If you want to be able to use a base theme's skins, you will need to add this line to your .info file.

skinr[options][inherit_skins] = true

mrfelton’s picture

Yes - thought about the other preprocess approach too - but seems like it would add a fair amount of duplication.

I'm not really clear why we are bringing inherit_skins into this discussion. inherit_skins is about inheriting defined skins, and was a D6 thing which is included in D7 in a slightly different way (you implement a hook to modify the behavior rather than add an option to the theme's .info file). This issue is about something completely different (although when I first opened the ticket I had thought that the answer lay in inherit_skins). This is about inheriting styles, hence I have used a different name for the 'inherit_styles' .info option.

Are you still of the opinion that this doesn't belong in Skinr core? And if so, why not? Seems like a pretty useful addition. Skinr already has the ability to inherit skins. Why not allow it to inherit applied styles too? Sorry if I'm missing the point on this one.

moonray’s picture

@mrfelton Sorry about rehashing the inherit_skins thing. I thought we were still on that. :-)

As for allowing the inheritance of Skinr settings (that's what they're called in code)... I'm waiting for some feedback from @jacine on this.

My main issue with this is the added overhead, and the fact that it takes away from the modularity that skin plugins provide since version 7.x.

mrfelton’s picture

@moonray - I don't think there is much in the way of overhead here. We call skinr_implements_api() to find out if 'Skinr settings' inheritance is enabled, and the skinr_implements_api() function uses a static cache. So all we are talking about is looking at the value of an already statically cached variable.

How does this take away from the modularity that skin plugins provide?

mrfelton’s picture

Status: Needs work » Needs review

Setting back to needs review, as I don't know what further work is required.

moonray’s picture

Issue tags: +Ensure hook_skinr_preprocess_alter() is always called to allow injecting skin configurations
StatusFileSize
new917 bytes

Attached patch ensure hook_skinr_preprocess_alter() is called regardless of whether or not skin configurations are found for the element in question.

This should allow custom modules to inject skin configurations.

Inheriting skin configuration from parent themes is an edge case. Enabling this might horribly break people's existing sites that aren't expecting that behavior.
So, I think with the above fix in place it should allow extending Skinr with a custom module to inject skin configuration and solve your problem while not breaking the site for 99% of use cases.

The code snippet in #5 should now be possible.

mrfelton’s picture

I don't really see how skin inheritance is an edge case. Themes have inheritance. Skins relate to themes, and so should have an inheritance option too. It makes no sense to require users to duplicate every single Skin configuration out to every single subtheme manually to make the base theme skin configurations available in subthemes too. Subthemes should be able to inherit skin configs just as they can other configs. It shouldn't need a module or custom code to do that. It should be an option in the theme settings, IMO.

Status: Needs review » Needs work
Issue tags: -Ensure hook_skinr_preprocess_alter() is always called to allow injecting skin configurations

The last submitted patch, skinr-preprocess_inject_skins-1554044-14.patch, failed testing.

moonray’s picture

Status: Needs work » Needs review
Issue tags: +Ensure hook_skinr_preprocess_alter() is always called to allow injecting skin configurations
moonray’s picture

I was under the impression that theme settings aren't inherited by sub themes. If theme settings aren't inherited, applied skin configurations should not be either.

Status: Needs review » Needs work

The last submitted patch, skinr-preprocess_inject_skins-1554044-14.patch, failed testing.

mrfelton’s picture

Your logic makes little sense to me. Themes can be configured to inherit from a base theme. That means that they share all attributes of the base theme. That is configured by setting a theme setting. The theme setting itself is not inherited - it is explicitly set in the sub theme. IMO, the same should be true of skinr. It should be able to inherit from the base theme, if configured to do so in the theme settings, making the sub theme act just like the base theme.

  • css can be inherited from a base theme
  • panels layouts can be inherited from a base theme
  • display suite layouts can be inherited from a base theme

All of the above help to reduce the need to duplicate countless amounts of duplication following the concept that a theme that inherits from a base theme should start out exactly like the parent theme, and should be able to extend that theme as simply as possible. Why should it not also be possible to inherit skinr configurations from a base theme? The reasoning I have heard so far includes:

> My main issue with this is the added overhead.
Where is the overhead? checking a statically cached variable from RAM hardly constitutes much in the way of overhead. Skinr has plenty of performance problems to be sure, but I don't think thats one of them.

> And the fact that it takes away from the modularity that skin plugins provide since version 7.x
How does letting people decide if the want their sub theme to inherit skinr applied styles from their base theme take away from the modularity that skin plugins provide?

> Inheriting skin configuration from parent themes is an edge case. Enabling this might horribly break people's existing sites that aren't expecting that behavior. So, I think with the above fix in place it should allow extending Skinr with a custom module to inject skin configuration and solve your problem while not breaking the site for 99% of use cases.
The setting would only affect users that explicitly enable it in their .info file - 99% of users would likely not do that, unless they all actually wanted style inheritance.

  • moonray committed e65fe76 on 8.x-2.x
    Issue #1554044 by mrfelton, moonray: Ensure hook_skinr_preprocess_alter...
astonvictor’s picture

Issue summary: View changes
Status: Needs work » Closed (outdated)
Issue tags: -

D7 reached its EOL back in January 2025, and there is no active release for D7 for this module anymore.
Development or support is not planned for D7. All D7-related issues are marked as outdated in a bunch.

Now that this issue is closed, please review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, please credit people who helped resolve this issue.