You are here

skinr.module in Skinr 6.2

Same filename and directory in other branches
  1. 8.2 skinr.module
  2. 6 skinr.module
  3. 7.2 skinr.module

File

skinr.module
View source
<?php

/**
 * Implementation of hook_help().
 */
function skinr_help($path, $arg) {
  switch ($path) {
    case 'admin/help#skinr':
      if (module_exists('advanced_help')) {
        return t('Visit the <a href="@skinr-help">help page</a> for full documentation.', array(
          '@skinr-help' => url('admin/advanced_help/skinr'),
        ));
      }
      else {
        return t('Please download and enable the <a href="http://drupal.org/project/advanced_help">Advanced Help</a> module for full Skinr documentation.');
      }
      break;
  }
}

/**
 * Implementation of hook_init().
 */
function skinr_init() {
  static $run = FALSE;
  if (!$run) {
    module_load_include('inc', 'skinr', 'skinr.handlers');
    skinr_module_include('skinr.inc');
    $run = TRUE;
  }
}

/**
 * Implementation of hook_preprocess().
 */
function skinr_preprocess(&$vars, $hook) {

  // Fix for update script.
  if (defined('MAINTENANCE_MODE')) {
    return;
  }
  static $data = NULL;

  // Caching the data returned from the following functions is reported to
  // improve performance.
  if (is_null($data)) {

    // Let's make sure this has been run. There have been problems where other
    // modules implement a theme function in their hook_init(), so we make doubly
    // sure that the includes are included.
    skinr_init();
    $data['current_theme'] = skinr_current_theme();
    $data['skinr_config'] = skinr_fetch_config();
    $data['theme_registry'] = theme_get_registry();
  }
  $original_hook = $hook;
  if (isset($data['theme_registry'][$hook]['original hook'])) {
    $original_hook = $data['theme_registry'][$hook]['original hook'];
  }
  foreach ($data['skinr_config'] as $module => $settings) {
    if (!empty($settings['preprocess'][$original_hook])) {
      $preprocess_settings = $settings['preprocess'][$original_hook];
      $sids = skinr_handler('preprocess_index_handler', 'preprocess', $preprocess_settings['index_handler'], $vars);
      if ($extracted = skinr_skin_extract($module, $sids, $settings, $data['current_theme'])) {
        foreach ($extracted['css'] as $file) {
          if ($file['enabled']) {
            _skinr_add_file($file['path'], 'css', $file['media']);
          }
        }
        foreach ($extracted['js'] as $file) {
          if ($file['enabled']) {
            _skinr_add_file($file['path'], 'js');
          }
        }
        if (!empty($extracted['template'])) {
          $vars['template_files'][] = $extracted['template'];
        }
        $vars['skinr'] = implode(' ', $extracted['classes']);
        $vars['skinr_array'] = $extracted['classes'];

        // Need to add a hook for skinr_ui to plug into.
        $context = array(
          'hook' => $hook,
          'vars' => &$vars,
          'skin' => &$extracted,
        );
        drupal_alter('skinr_preprocess', $context);

        // Reset styles to make sure all are included.
        $vars['styles'] = drupal_get_css();
        $vars['scripts'] = drupal_get_js();
      }
    }
  }
}
function skinr_skin_extract($module, $sids, $settings, $theme = NULL, $reset = FALSE) {
  if (empty($sids)) {
    return FALSE;
  }
  if (!is_array($sids)) {
    $sids = array(
      $sids,
    );
  }
  if (is_null($theme)) {
    $theme = skinr_current_theme();
  }
  $info = skinr_skin_data();
  $extracted = array(
    'module' => $module,
    'sids' => $sids,
    'classes' => array(),
    'css' => array(),
    'js' => array(),
    'template' => array(),
  );
  $skins = array();
  foreach ($sids as $sid) {
    if ($skinr = skinr_get($theme, $module, $sid, $reset)) {
      $skins = $skinr->skins + $skins;
    }

    // Only need to reset the first time.
    $reset = FALSE;
  }

  // Allow other modules to alter the skinr skins array.
  // @todo Fix this to work with skinr ui.
  drupal_alter('skinr_skins', $skins, $module, $sids, $settings);
  $extracted['css'] = skinr_skin_get_files($skins, 'css', $theme);
  $extracted['js'] = skinr_skin_get_files($skins, 'js', $theme);

  // Add template files.
  if (!empty($skins['_template'])) {
    $extracted['template'] = $skins['_template'];
    unset($skins['_template']);
  }
  $extracted['classes'] = skinr_flatten_skins_array($skins);
  return $extracted;
}

/**
 * Helper function to fetch all css or js files from an array of skins.
 *
 * @param $skins
 *   A an array of available skins.
 * @param $type
 *   Either 'css' or 'js', depending on which files you wish to retrieve from
 *   these skins.
 * @param $theme
 *   The theme from which to grab these files. Defaults to the current theme.
 *
 * @return
 *   An array of file data.
 */
function skinr_skin_get_files($skins, $type, $theme = NULL) {
  if (empty($theme)) {
    $theme = skinr_current_theme();
  }
  $info = skinr_skin_data();
  $files = array();
  if ($type == 'css') {
    foreach ($skins as $skin => $classes) {

      // Add custom CSS files.
      if (isset($info[$theme]->skins[$skin])) {
        if (!empty($info[$theme]->skins[$skin]['stylesheets'])) {
          foreach ($info[$theme]->skins[$skin]['stylesheets'] as $media => $stylesheets) {
            foreach ($stylesheets as $file => $path) {
              $files[] = array(
                'file' => $file,
                'path' => $path,
                'media' => $media,
                'enabled' => TRUE,
                'skin' => $skin,
                'options' => 0,
              );
            }
          }
        }
        foreach ($info[$theme]->skins[$skin]['options'] as $option_id => $option) {
          if (!empty($option['stylesheets'])) {
            foreach ($option['stylesheets'] as $media => $stylesheets) {
              foreach ($stylesheets as $file => $path) {
                $enabled = FALSE;
                if (is_array($classes)) {
                  if (in_array($option['class'], $classes)) {
                    $enabled = TRUE;
                  }
                }
                else {
                  if ($option['class'] == $classes) {
                    $enabled = TRUE;
                  }
                }
                $files[] = array(
                  'file' => $file,
                  'path' => $path,
                  'media' => $media,
                  'enabled' => $enabled,
                  'skin' => $skin,
                  'options' => $option_id,
                );
              }
            }
          }
        }
      }
    }
  }
  elseif ($type == 'js') {
    foreach ($skins as $skin => $classes) {

      // Add custom JS files.
      if (isset($info[$theme]->skins[$skin])) {
        if (isset($info[$theme]->skins[$skin]['scripts'])) {
          foreach ($info[$theme]->skins[$skin]['scripts'] as $file => $path) {
            $files[] = array(
              'file' => $file,
              'path' => $path,
              'enabled' => TRUE,
              'skin' => $skin,
              'options' => 0,
            );
          }
        }
        foreach ($info[$theme]->skins[$skin]['options'] as $option_id => $option) {
          if (isset($option['scripts'])) {
            foreach ($option['scripts'] as $file => $path) {
              $enabled = FALSE;
              if (is_array($classes)) {
                if (in_array($option['class'], $classes)) {
                  $enabled = TRUE;
                }
              }
              else {
                if ($option['class'] == $classes) {
                  $enabled = TRUE;
                }
              }
              $files[] = array(
                'file' => $file,
                'path' => $path,
                'enabled' => $enabled,
                'skin' => $skin,
                'options' => $option_id,
              );
            }
          }
        }
      }
    }
  }
  return $files;
}

/**
 * Helper fuction to add CSS and JS files.
 *
 * The function checks an array of paths for the existence of the file to account for base themes.
 */
function _skinr_add_file($filename, $type, $media = NULL) {
  if (file_exists($filename)) {
    if ($type == 'css') {
      drupal_add_css($filename, 'theme', $media);
    }
    else {
      drupal_add_js($filename, 'theme');
    }
  }
}

/**
 * Helper function to flatten an array of classes settings.
 */
function skinr_flatten_skins_array($skins) {
  $return = array();
  foreach ($skins as $entry) {
    if (is_array($entry)) {
      foreach ($entry as $subentry) {
        if (!empty($subentry)) {
          $return[] = check_plain($subentry);
        }
      }
    }
    elseif (!empty($entry)) {
      $return[] = check_plain($entry);
    }
  }
  return $return;
}

// ------------------------------------------------------------------
// Page rule functions.

/**
 * Save a skinr page rule object.
 */
function skinr_rule_save($rule) {
  drupal_write_record('skinr_rules', $rule, !empty($rule->rid) ? array(
    'rid',
  ) : array());
}

/**
 * Load a skinr page rule object.
 */
function skinr_rule_load($rid = NULL) {
  if (is_null($rid)) {
    $rules = array();
    $result = db_query("SELECT * FROM {skinr_rules}");
    while ($rule = db_fetch_object($result)) {
      $rule->roles = unserialize($rule->roles);
      $rules[] = $rule;
    }
    return $rules;
  }
  else {
    $result = db_query("SELECT * FROM {skinr_rules} WHERE rid = %d", $rid);
    if ($rule = db_fetch_object($result)) {
      $rule->roles = unserialize($rule->roles);
      return $rule;
    }
    return FALSE;
  }
}

/**
 * Delete a skinr page rule object.
 */
function skinr_rule_delete($rid) {
  if ($rule = skinr_rule_load($rid)) {
    db_query("DELETE FROM {skinr_rules} WHERE rid = %d", $rule->rid);
    db_query("DELETE FROM {skinr} WHERE module = '%s' AND sid = '%s'", 'page', $rule->rid);
  }
}
function skinr_rule_visible($rid) {
  global $user;
  if ($rule = skinr_rule_load($rid)) {
    $page_match = TRUE;
    if (!empty($record['roles']) && $user->uid != 1 && !count(array_intersect(array_keys($user->roles), $rule->roles))) {
      return FALSE;
    }

    // Match path if necessary
    if ($rule->pages) {
      if ($rule->visibility < 2) {
        $path = drupal_get_path_alias($_GET['q']);

        // Compare with the internal and path alias (if any).
        $page_match = drupal_match_path($path, $rule->pages);
        if ($path != $_GET['q']) {
          $page_match = $page_match || drupal_match_path($_GET['q'], $rule->pages);
        }

        // When $rule->visibility has a value of 0, the item is displayed on
        // all pages except those listed in $rule->pages. When set to 1, it
        // is displayed only on those pages listed in $rule->pages.
        $page_match = !($rule->visibility xor $page_match);
      }
      else {

        // PHP.
        $page_match = drupal_eval($rule->pages);
      }
    }
    return $page_match;
  }
  return FALSE;
}

// ------------------------------------------------------------------
// Include file helpers.

/**
 * Load skinr files on behalf of modules.
 */
function skinr_module_include($file) {
  foreach (skinr_get_module_apis() as $module => $info) {
    if (file_exists("./{$info['path']}/{$module}.{$file}")) {
      require_once "./{$info['path']}/{$module}.{$file}";
    }
  }
}

/**
 * Get a list of modules that support skinr.
 */
function skinr_get_module_apis() {
  static $cache = NULL;
  if (is_null($cache)) {
    $cache = array();
    foreach (module_implements('skinr_api') as $module) {
      $function = $module . '_skinr_api';
      $info = $function();
      if (isset($info['api']) && $info['api'] == 1.0) {
        if (!isset($info['path'])) {
          $info['path'] = drupal_get_path('module', $module);
        }
        $cache[$module] = $info;
      }
    }
  }
  return $cache;
}

// -----------------------------------------------------------------------
// Skinr data handling functions.

/**
 * Validate a skinr object.
 *
 * @param $skinr
 *   A skinr object.
 *
 * @return
 *   TRUE on success, FALSE on failure.
 */
function skinr_validate(&$skinr) {
  if (!isset($skinr->theme) || !isset($skinr->module) || !isset($skinr->sid) || !isset($skinr->skins)) {
    return FALSE;
  }
  if (!isset($skinr->settings)) {
    $skinr->settings = array();
  }
  if (!is_array($skinr->skins) || !is_array($skinr->settings)) {
    return FALSE;
  }

  // Strip empty skins.
  $skinr->skins = _skinr_array_strip_empty($skinr->skins);
  return TRUE;
}

/**
 * Save a skinr object.
 *
 * @param $skinr
 *   A skinr object.
 *
 * @return
 *   TRUE on success, FALSE on failure.
 */
function skinr_set($skinr) {

  // Make sure we're getting valid data.
  if (!skinr_validate($skinr)) {
    return FALSE;
  }
  if (empty($skinr->skins) && empty($skinr->settings)) {

    // Delete the db entry if it exists.
    db_query("DELETE FROM {skinr} WHERE theme = '%s' AND module = '%s' AND sid = '%s'", $skinr->theme, $skinr->module, $skinr->sid);
  }
  else {

    // Let's save the data.
    if (skinr_get($skinr->theme, $skinr->module, $skinr->sid) !== FALSE) {

      // Record exists, so let's update.
      drupal_write_record('skinr', $skinr, array(
        'theme',
        'module',
        'sid',
      ));
    }
    else {

      // Insert a new record.
      drupal_write_record('skinr', $skinr);
    }
  }
  return TRUE;
}

/**
 * Retrieves the desired skinr object.
 *
 * @return
 *   A skinr object if both $module and $sid are specified. An array of skinr
 *   objects if only $module is specified. An array of all skinr objects for a
 *   theme if neither $module nor $sid is specified. FALSE on failure.
 */
function skinr_get($theme = NULL, $module = NULL, $sid = NULL, $reset = FALSE) {
  static $cache = array();
  if (is_null($theme)) {
    $theme = skinr_current_theme();
  }
  if ($reset) {
    $cache = array();
  }
  if (!isset($cache[$theme][$module][$sid])) {
    if (!isset($cache[$theme])) {
      $cache[$theme] = array();
    }
    if (!is_null($module) && !isset($cache[$theme][$module])) {
      $cache[$theme][$module] = array();
    }
    if (!is_null($module) && !is_null($sid)) {

      // Fetch just this sid.
      $result = db_query("SELECT theme, module, sid, settings, skins FROM {skinr} WHERE theme = '%s' AND module = '%s' AND sid = '%s'", $theme, $module, $sid);
    }
    elseif (!is_null($module)) {

      // Fetch all settings for this theme and module.
      $result = db_query("SELECT theme, module, sid, settings, skins FROM {skinr} WHERE theme = '%s' AND module = '%s'", $theme, $module);
    }
    else {

      // Fetch all settings for this theme.
      $result = db_query("SELECT theme, module, sid, settings, skins FROM {skinr} WHERE theme = '%s'", $theme);
    }
    while ($skinr = db_fetch_object($result)) {
      $skinr->settings = unserialize($skinr->settings);
      $skinr->skins = unserialize($skinr->skins);
      $cache[$skinr->theme][$skinr->module][$skinr->sid] = $skinr;
    }
  }
  if (is_null($sid) && is_null($module)) {

    // Return all the skinrs for the theme.
    if (isset($cache[$theme])) {
      return $cache[$theme];
    }
  }
  elseif (is_null($sid)) {

    // Return all the skinrs for the module.
    if (isset($cache[$theme][$module])) {
      return $cache[$theme][$module];
    }
  }
  elseif (isset($cache[$theme][$module][$sid])) {
    return $cache[$theme][$module][$sid];
  }
  return FALSE;
}

/**
 * Helper function to remove empty skins from an array.
 */
function _skinr_array_strip_empty($array) {
  $new_array = array();
  foreach ($array as $key => $value) {
    if (is_array($value)) {
      $value = _skinr_array_strip_empty($value);
    }
    if (!empty($value)) {
      $new_array[$key] = $value;
    }
  }
  return $new_array;
}

/**
 * Helper function to retrieve the current theme.
 * The global variable $theme_key doesn't work for our purposes when an admin
 * theme is enabled.
 *
 * @param $exculde_admin_theme
 *   Optional. Set to TRUE to exclude the admin theme from posible themes to
 *   return.
 */
function skinr_current_theme($exclude_admin_theme = FALSE) {
  global $user, $custom_theme;
  if (!empty($user->theme)) {
    $current_theme = $user->theme;
  }
  elseif (!empty($custom_theme) && !($exclude_admin_theme && $custom_theme == variable_get('admin_theme', '0'))) {

    // Don't return the admin theme if we're editing skinr settings.
    $current_theme = $custom_theme;
  }
  else {
    $current_theme = variable_get('theme_default', 'garland');
  }
  return $current_theme;
}

/**
 * Prepare defaults for skins.
 *
 * @return
 *   An array of default skinset settings.
 */
function skinr_skins_default() {
  return array(
    'description' => '',
    'screenshot' => 'screenshot.png',
    'php' => DRUPAL_MINIMUM_PHP,
    'skinr' => array(),
  );
}

/**
 * Prepare defaults for skinr options.
 *
 * @return
 *   An array of default skinset options settings.
 */
function skinr_group_default() {
  return array(
    'title' => '',
    'description' => '',
    'collapsible' => TRUE,
    'collapsed' => FALSE,
    'weight' => NULL,
  );
}

/**
 * Prepare defaults for skins.
 *
 * @return
 *   An array of default skins settings.
 */
function skinr_skin_default() {
  return array(
    'title' => '',
    'type' => 'checkboxes',
    'description' => '',
    'features' => array(
      '*',
    ),
    'templates' => array(),
    'group' => '',
    'options' => array(),
    'stylesheets' => array(),
    'scripts' => array(),
    'weight' => NULL,
  );
}

/**
 * Retrieves all the Skinr skins from theme parents. Theme skins
 * will override any skins of the same name from its parents.
 */
function skinr_inherited_skins($theme) {
  $themes = system_theme_data();
  $all_skins = $skins = array();
  $base_theme = !empty($themes[$theme]->info['base theme']) ? $themes[$theme]->info['base theme'] : '';
  while ($base_theme) {

    // Add in path info here.
    $base_skins = !empty($themes[$base_theme]->info['skinr']) ? (array) $themes[$base_theme]->info['skinr'] : array();
    $base_path = $path_root = dirname($themes[$base_theme]->filename);
    _skinr_add_paths_to_files($base_skins, $base_path);
    $all_skins[] = $base_skins;
    $base_theme = !empty($themes[$base_theme]->info['base theme']) ? $themes[$base_theme]->info['base theme'] : '';
  }
  array_reverse($all_skins);
  foreach ($all_skins as $new_skin) {
    $skins = array_merge($skins, $new_skin);
  }
  return $skins;
}

/**
 * Helper function to scan and collect skin .info data.
 *
 * @return
 *   An associative array of skins information.
 */
function _skinr_skins_data() {
  static $skins_info = array();
  if (empty($skins_info)) {

    // Find skins.
    $mask = '\\.info$';
    $directory = 'skins';
    $skinsets = drupal_system_listing($mask, $directory);

    // Find skins in theme folders.
    $themes = system_theme_data();
    foreach ($themes as $theme) {
      $dir = dirname($theme->filename) . '/' . $directory;
      $skinsets = array_merge($skinsets, file_scan_directory($dir, $mask, array(
        '.',
        '..',
        'CVS',
      ), 0, TRUE, 'name', 1));
    }

    // Find skins in module folders.
    foreach (skinr_get_module_apis() as $module => $info) {
      if (isset($info['skins']) && $info['skins'] == TRUE) {
        $dir = dirname($info['path'] . '/' . $directory);
        $skinsets = array_merge($skinsets, file_scan_directory($dir, $mask, array(
          '.',
          '..',
          'CVS',
        ), 0, TRUE, 'name', 1));
      }
    }
    $defaults = skinr_skins_default();
    foreach ($skinsets as $key => $skinset) {
      $skinsets[$key]->info = drupal_parse_info_file($skinset->filename) + $defaults;

      // Give the screenshot proper path information.
      if (!empty($skinsets[$key]->info['screenshot'])) {
        $skinsets[$key]->info['screenshot'] = dirname($skinsets[$key]->filename) . '/' . $skinsets[$key]->info['screenshot'];
      }

      // Invoke hook_skinr_info_alter() to give installed modules a chance to
      // modify the data in the .info files if necessary.
      drupal_alter('skinr_info', $skinsets[$key]->info, $skinsets[$key]);
    }
    $skins_info = $skinsets;
  }
  return $skins_info;
}

/**
 * Helper function to process a skin or theme .info file.
 *
 * @return
 *    A skinset.
 */
function _skinr_skinset($info) {
  $skinset = array(
    'options' => array(
      'groups' => array(),
    ),
    'skins' => array(),
  );
  if (!empty($info->info['skinr'])) {
    $path_root = dirname($info->filename);
    $skinr_info = (array) $info->info['skinr'];

    // Store skinr options.
    if (!empty($skinr_info['options'])) {
      $skinset['options'] = $skinr_info['options'];
      unset($skinr_info['options']);
      if (!isset($skinset['options']['groups'])) {
        $skinset['options']['groups'] = array();
      }
      $defaults = skinr_group_default();
      foreach ($skinset['options']['groups'] as $id => $group) {
        $skinset['options']['groups'][$id] = array_merge($defaults, $skinset['options']['groups'][$id]);
        $skinset['options']['groups'][$id]['collapsible'] = (bool) $skinset['options']['groups'][$id]['collapsible'];
        $skinset['options']['groups'][$id]['collapsed'] = (bool) $skinset['options']['groups'][$id]['collapsed'];
        $skinset['options']['groups'][$id]['weight'] = $skinset['options']['groups'][$id]['weight'];
      }
    }

    // Add paths to $skinr_info.
    _skinr_add_paths_to_files($skinr_info, $path_root);

    // Inherit skins from parent theme, if inherit_skins is set to true.
    if (!empty($skinset['options']['inherit_skins'])) {

      // Paths get automatically added to base theme info.
      $base_info = skinr_inherited_skins($info->name);

      // Merge base theme and current.
      $skinr_info = array_merge($base_info, $skinr_info);
    }
    $defaults = skinr_skin_default();
    foreach ($skinr_info as $id => $skin) {
      if (!is_array($skin)) {
        continue;
      }
      $skinset['skins'][$id] = array(
        'title' => isset($skin['title']) ? $skin['title'] : $defaults['title'],
        'type' => isset($skin['type']) ? $skin['type'] : $defaults['type'],
        'description' => isset($skin['description']) ? $skin['description'] : $defaults['description'],
        'features' => isset($skin['features']) ? $skin['features'] : $defaults['features'],
        'templates' => isset($skin['templates']) ? $skin['templates'] : $defaults['templates'],
        'group' => !empty($skin['group']) && !empty($skinset['options']['groups'][$skin['group']]) ? $skin['group'] : $defaults['group'],
        'options' => isset($skin['options']) ? $skin['options'] : $defaults['options'],
        'stylesheets' => isset($skin['stylesheets']) ? $skin['stylesheets'] : $defaults['stylesheets'],
        'scripts' => isset($skin['scripts']) ? $skin['scripts'] : $defaults['scripts'],
        'weight' => isset($skin['weight']) ? $skin['weight'] : $defaults['weight'],
      );
    }
  }
  return $skinset;
}
function _skinr_add_paths_to_files(&$skinr_info, $path_root) {
  foreach ($skinr_info as $id => $skin) {
    if (!is_array($skin)) {
      continue;
    }

    // Give the stylesheets proper path information.
    if (!empty($skin['stylesheets'])) {
      $skinr_info[$id]['stylesheets'] = _skinr_add_path_to_files($skin['stylesheets'], $path_root, 'css');
    }

    // Give the scripts proper path information.
    if (!empty($skin['scripts'])) {
      $skinr_info[$id]['scripts'] = _skinr_add_path_to_files($skin['scripts'], $path_root, 'js');
    }
    if (!empty($skin['options'])) {
      foreach ($skin['options'] as $oid => $option) {
        if (!empty($option['stylesheets'])) {
          $skinr_info[$id]['options'][$oid]['stylesheets'] = _skinr_add_path_to_files($option['stylesheets'], $path_root, 'css');
        }
        if (isset($option['scripts'])) {
          $skinr_info[$id]['options'][$oid]['scripts'] = _skinr_add_path_to_files($option['scripts'], $path_root, 'js');
        }
      }
    }
  }
}

/**
 * Helper function to prepend a path to an array of stylesheets or scripts in a .info file.
 *
 * @param $files
 *   A an array of filenames that need the path prepended.
 * @param $path
 *   The path to prepend.
 * @param $type
 *   Either 'css' or 'js', depending on which files you wish to retrieve from
 *   these skins.
 *
 * @return
 *    An array of files with the root path added.
 */
function _skinr_add_path_to_files($files, $path, $type) {
  if ($type == 'css') {
    $pathed_stylesheets = array();
    foreach ($files as $media => $stylesheets) {
      foreach ($stylesheets as $stylesheet) {
        $pathed_stylesheets[$media][$stylesheet] = $path . '/' . $stylesheet;
      }
    }
    return $pathed_stylesheets;
  }
  elseif ($type == 'js') {
    $pathed_scripts = array();
    foreach ($files as $script) {
      $pathed_scripts[$script] = $path . '/' . $script;
    }
    return $pathed_scripts;
  }
  return FALSE;
}

/**
 * Helper function to process an array of skins or themes .info files.
 *
 * @param $type
 *   Either 'theme' or 'skinset'.
 * @param $refresh
 *   Whether to reload the list of skinsets from the database or not.
 *
 * @return
 *    An array of skinsets.
 */
function skinr_skinsets($type, $refresh = FALSE) {

  // Fix for update script.
  if (defined('MAINTENANCE_MODE')) {
    return array();
  }
  static $skinsets = array(
    'theme' => array(),
    'skinset' => array(),
  );
  if ($refresh) {
    $skinsets[$type] = array();
  }
  if (empty($skinsets[$type])) {
    $themes = system_theme_data();
    if ($type == 'theme') {
      foreach ($themes as $theme) {
        $skinset = new StdClass();
        $skinset->filename = $theme->filename;
        $skinset->name = $theme->name;
        $skinset->status = isset($theme->status) ? 1 : 0;
        $skinset->info = $theme->info;
        $skinsets[$type][$skinset->name] = $skinset;
      }
    }
    elseif ($type == 'skinset') {

      // Rebuild if needed.
      if (variable_get('skinr_rebuild_skinset_data', FALSE)) {
        skinr_rebuild_skinset_data();
      }
      $result = db_query("SELECT * FROM {skinr_skinsets}");
      while ($skinset = db_fetch_object($result)) {
        if (file_exists($skinset->filename)) {
          $skinset->info = unserialize($skinset->info);
          $skinsets[$type][$skinset->name] = $skinset;
        }
      }
    }
    $default_status = array();
    foreach ($themes as $theme) {
      $default_status[$theme->name] = $theme->name;
    }
    foreach ($skinsets[$type] as $key => $skinset) {
      $skinset->type = $type;
      $additional = _skinr_skinset($skinset);
      $skinset->options = $additional['options'];
      $skinset->skins = $additional['skins'];
      $statuses = skinr_skinset_statuses($skinset->name);
      foreach ($skinset->skins as $skin_name => $skin) {
        $skinset->skins[$skin_name]['status'] = !empty($statuses[$skin_name]) ? $statuses[$skin_name] : $default_status;
      }
    }
  }
  return $skinsets[$type];
}

/**
 * Return an array of statuses of each skin in a skinset for each theme.
 *
 * @param $skinset_name
 *   The name of the skinset of which to load the statuses.
 * @param $refresh
 *   Whether to reload the list of statuses for a skin from the database or not.
 *
 * @return
 *   Array of statuses for individual skins in a skinset.
 */
function skinr_skinset_statuses($skinset_name, $refresh = FALSE) {
  static $statuses = array();
  if (isset($refresh)) {
    $statuses[$skinset_name] = array();
  }
  if (empty($statuses[$skinset_name])) {
    $result = db_query("SELECT * FROM {skinr_skins} WHERE name = '%s'", $skinset_name);
    while ($skinr_skin = db_fetch_object($result)) {
      $statuses[$skinset_name][$skinr_skin->skin] = unserialize($skinr_skin->status);
    }
  }
  return $statuses[$skinset_name];
}

/**
 * Rebuild, save, and return data about all currently available skinsets.
 *
 * @return
 *   Array of all available skinsets and their data.
 */
function skinr_rebuild_skinset_data() {

  // Fix for update script.
  if (defined('MAINTENANCE_MODE')) {
    return array();
  }
  $skinsets = _skinr_skins_data();
  skinr_get_files_database($skinsets);
  db_query("DELETE FROM {skinr_skinsets}");
  foreach ($skinsets as $skinset) {
    db_query("INSERT INTO {skinr_skinsets} (filename, name, status, info) VALUES ('%s', '%s', '%s', '%s')", $skinset->filename, $skinset->name, isset($skinset->status) ? $skinset->status : 0, serialize($skinset->info));
  }
  variable_set('skinr_rebuild_skinset_data', FALSE);
  return $skinsets;
}

/**
 * Implementation of hook_flush_caches().
 */
function skinr_flush_caches() {
  variable_set('skinr_rebuild_skinset_data', TRUE);
  return array();
}

/**
 * Retrieves the current status of an array of files in the skinr_skinsets table.
 *
 * @param $files
 *   An array of files to check.
 */
function skinr_get_files_database(&$files) {

  // Extract current files from database.
  $result = db_query("SELECT filename, name, status FROM {skinr_skinsets}");
  while ($file = db_fetch_object($result)) {
    if (isset($files[$file->name]) && is_object($files[$file->name])) {
      $file->uri = $file->filename;
      foreach ($file as $key => $value) {
        if (!isset($files[$file->name]) || !isset($files[$file->name]->{$key})) {
          $files[$file->name]->{$key} = $value;
        }
      }
    }
  }
}

/**
 * Themes are allowed to set Skinr skins in their .info files.
 *
 * @return
 *    An array of skinsets keyed by themename.
 *
 * @todo Use DB caching. No need to keep processing things every page load.
 */
function skinr_skin_data() {
  static $cache = NULL;
  if (is_null($cache)) {
    $skins_skinsets = skinr_skinsets('skinset');
    $themes_skinsets = skinr_skinsets('theme');

    // Need to merge all skins skinsets into a single list of skins.
    // Also merge in the groups information.
    $additional_skins = array();
    $groups = array();
    foreach ($skins_skinsets as $key => $skinset) {
      if (!empty($skinset->skins) && $skinset->status == 1) {
        $additional_skins += $skinset->skins;
      }
      if (!empty($skinset->options['groups'])) {
        $groups += $skinset->options['groups'];
      }
    }

    // Merge the additional skins into each theme, even if that theme has no
    // skinr data.
    $themes = list_themes();
    foreach ($themes as $theme) {
      if ($theme->status != 1) {
        continue;
      }
      if (isset($themes_skinsets[$theme->name])) {
        $cache[$theme->name] = $themes_skinsets[$theme->name];
        $cache[$theme->name]->skins += $additional_skins;
        $cache[$theme->name]->options['groups'] += $groups;
      }
      else {
        $cache[$theme->name] = array(
          'options' => array(
            'groups' => $groups,
          ),
          'skins' => $additional_skins,
        );
      }
    }
  }
  return $cache;
}

/**
 * Fetch Skinr configuration data from modules.
 */
function skinr_fetch_config() {
  static $cache = NULL;
  if (is_null($cache)) {
    $cache = module_invoke_all('skinr_config');
    foreach (module_implements('skinr_config_alter') as $module) {
      $function = $module . '_skinr_config_alter';
      $function($cache);
    }
  }
  return $cache;
}

/**
 * Fetch default configuration data for modules.
 */
function _skinr_fetch_config_defaults($setting) {
  switch ($setting) {
    case 'form':
      $data = array(
        'access_handler' => 'skinr_access_handler',
        'data_handler' => 'skinr_data_handler',
        'submit_handler' => 'skinr_submit_handler',
        'submit_handler_attach_to' => array(
          '#submit',
        ),
        'skinr_title' => t('Skinr'),
        'skinr_weight' => 1,
        'title' => '',
        'description' => t('Manage which skins you want to apply to the hooks'),
        'collapsed' => TRUE,
        'weight' => 0,
      );
      return $data;
  }
}

/**
 * Execute a module's data handler.
 */
function skinr_handler($type, $op, $handler, &$a3, $a4 = NULL, $a5 = NULL, $a6 = NULL, $a7 = NULL) {
  if (is_callable($handler)) {
    switch ($type) {
      case 'preprocess_index_handler':
        return $handler($a3);
      case 'preprocess_hook_callback':
        return $handler($a3, $a4);
      case 'data_handler':
      case 'submit_handler':
        return $handler($a3, $a4, $a5, $a6, $a7);
      default:
        return $handler($op, $a3, $a4);
    }
  }
}

Functions

Namesort descending Description
skinr_current_theme Helper function to retrieve the current theme. The global variable $theme_key doesn't work for our purposes when an admin theme is enabled.
skinr_fetch_config Fetch Skinr configuration data from modules.
skinr_flatten_skins_array Helper function to flatten an array of classes settings.
skinr_flush_caches Implementation of hook_flush_caches().
skinr_get Retrieves the desired skinr object.
skinr_get_files_database Retrieves the current status of an array of files in the skinr_skinsets table.
skinr_get_module_apis Get a list of modules that support skinr.
skinr_group_default Prepare defaults for skinr options.
skinr_handler Execute a module's data handler.
skinr_help Implementation of hook_help().
skinr_inherited_skins Retrieves all the Skinr skins from theme parents. Theme skins will override any skins of the same name from its parents.
skinr_init Implementation of hook_init().
skinr_module_include Load skinr files on behalf of modules.
skinr_preprocess Implementation of hook_preprocess().
skinr_rebuild_skinset_data Rebuild, save, and return data about all currently available skinsets.
skinr_rule_delete Delete a skinr page rule object.
skinr_rule_load Load a skinr page rule object.
skinr_rule_save Save a skinr page rule object.
skinr_rule_visible
skinr_set Save a skinr object.
skinr_skinsets Helper function to process an array of skins or themes .info files.
skinr_skinset_statuses Return an array of statuses of each skin in a skinset for each theme.
skinr_skins_default Prepare defaults for skins.
skinr_skin_data Themes are allowed to set Skinr skins in their .info files.
skinr_skin_default Prepare defaults for skins.
skinr_skin_extract
skinr_skin_get_files Helper function to fetch all css or js files from an array of skins.
skinr_validate Validate a skinr object.
_skinr_add_file Helper fuction to add CSS and JS files.
_skinr_add_paths_to_files
_skinr_add_path_to_files Helper function to prepend a path to an array of stylesheets or scripts in a .info file.
_skinr_array_strip_empty Helper function to remove empty skins from an array.
_skinr_fetch_config_defaults Fetch default configuration data for modules.
_skinr_skinset Helper function to process a skin or theme .info file.
_skinr_skins_data Helper function to scan and collect skin .info data.