help page for full documentation.', array('@skinr-help' => url('admin/advanced_help/skinr'))); } else { return t('Please download and enable the Advanced Help module for full Skinr documentation.'); } break; } } /** * Implements hook_hook_info(). */ function skinr_hook_info() { $hooks = array( 'skinr_api_2', ); $hooks = array_fill_keys($hooks, array( 'group' => 'skinr', )); return $hooks; } /** * Clears cached Skinr information. */ function skinr_cache_reset() { cache_clear_all('skinr_', 'cache', TRUE); } /** * Implements hook_module_implements_alter(). */ function skinr_module_implements_alter(&$implementations, $hook) { // Run Skinr first to avoid issues with other modules during hook_init(). if ($hook == 'init') { $skinr['skinr'] = $implementations['skinr']; unset($implementations['skinr']); $implementations = array_merge($skinr, $implementations); } } /** * Implements hook_init(). * * @todo Kill me. Entirely. */ function skinr_init() { module_load_include('inc', 'skinr', 'skinr.handlers'); skinr_load_includes(); } /** * Implements hook_preprocess(). * * @todo Account for Drupal's caching being enabled and make it work. */ function skinr_preprocess(&$variables, $hook) { // Fix for update script. if ($hook == 'maintenance_page') { return; } $config = skinr_get_config_info(); $current_theme = skinr_current_theme(); $theme_registry = theme_get_registry(); $original_hook = (isset($theme_registry[$hook]['original hook']) ? $theme_registry[$hook]['original hook'] : $hook); foreach ($config as $module => $module_settings) { if (!empty($module_settings['preprocess'][$original_hook])) { $preprocess_settings = $module_settings['preprocess'][$original_hook]; $sids = skinr_handler('preprocess_index_handler', 'preprocess', $preprocess_settings['index_handler'], $variables); // @todo Kill skinr_skin_extract(), and only store what has been // configured, enabled, and should be actively applied, in order to use // drupal_process_attached(). if ($extracted = skinr_skin_extract($module, $sids, $current_theme)) { foreach ($extracted['css'] as $file) { if ($file['enabled']) { drupal_add_css($file['path'], $file['file_options']); } } foreach ($extracted['js'] as $file) { if ($file['enabled']) { drupal_add_js($file['path'], $file['file_options']); } } $variables['classes_array'] = array_merge($variables['classes_array'], $extracted['classes']); // Invoke hook_skinr_preprocess_alter() in all modules. $context = array( 'hook' => $hook, 'variables' => &$variables, 'skin' => &$extracted, ); drupal_alter('skinr_preprocess', $context); } } } } /** * Helper function to extract classes, JS and CSS files. * * @param $module * The module these settings applies to. * @param $sids * The settings ID, or an array of settings IDs. * @param $settings * Skinr configuration data for the desired module. * @param $theme * The theme these settings apply to. If no theme name is provided, the * current theme will be used. * * @return * An array containing the module, sids, classes, CSS, JS, template to be * applied. * * @todo Rename this function to something more indicative of its function. * @todo Rename $sids to something more descriptive; these are skin ids. */ function skinr_skin_extract($module, $sids, $theme = NULL) { if (empty($sids)) { return FALSE; } if (!is_array($sids)) { $sids = array($sids); } if (!isset($theme)) { $theme = skinr_current_theme(); } $extracted = array( 'module' => $module, 'sids' => $sids, 'classes' => array(), 'css' => array(), 'js' => array(), ); $options = array(); foreach ($sids as $sid) { if ($skin = skinr_skin_load($theme, $module, $sid)) { $options = $skin->skins + $options; } } $extracted['css'] = skinr_skin_get_files($options, 'css', $theme); $extracted['js'] = skinr_skin_get_files($options, 'js', $theme); $extracted['classes'] = skinr_flatten_skins_array($options); return $extracted; } /** * Helper function to fetch all CSS or JS files from an array of skins. * * @param $skin_options * A an array of skin options. * @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($skin_options, $type, $theme = NULL) { if (empty($theme)) { $theme = skinr_current_theme(); } $skin_infos = skinr_get_skin_info(); $files = array(); if (!empty($skin_options['_options'])) { foreach ($skin_options['_options'] as $skin_name => $skin_option) { if (!is_array($skin_options)) { $skin_options = array($skin_options); } // Check if the $skin_name is enabled for this theme. if (!empty($skin_infos[$skin_name]['status'][$theme])) { // Check if this skin has any stylesheets attached to it. if (!empty($skin_infos[$skin_name]['attached'][$type])) { foreach ($skin_infos[$skin_name]['attached'][$type] as $file) { if (is_array($file)) { $path = $file[0]; $file_options = count($file) > 1 ? $file[1] : NULL; } else { $path = $file; $file_options = NULL; } $files[$path] = array( 'file' => basename($path), 'path' => $path, 'file_options' => $file_options, 'enabled' => TRUE, 'skin' => $skin_name, 'skin_option' => NULL, ); } } foreach ($skin_infos[$skin_name]['options'] as $skin_info_option_name => $skin_info_option) { if (!empty($skin_info_option['attached'][$type])) { foreach ($skin_info_option['attached'][$type] as $file) { $enabled = FALSE; if (_skinr_in_multiarray($skin_info_option_name, $skin_options)) { $enabled = TRUE; } if (is_array($file)) { $path = $file[0]; $file_options = count($file) > 1 ? $file[1] : NULL; } else { $path = $file; $file_options = NULL; } $files[$path] = array( 'file' => basename($path), 'path' => $path, 'file_options' => $file_options, 'skin' => $skin_name, 'skin_option' => $skin_info_option_name, ); // Allow for other options to set the same file; make sure it's // enabled when required. $files[$path]['enabled'] = (!empty($files[$path]['enabled']) ? $files[$path]['enabled'] : FALSE) || $enabled; } } } } } } return $files; } /** * Checks if a value exists in a multi-dimensional array. * * @param $needle * The value to find. * @param $haystack * The array. * * @return * Returns TRUE if $needle is found in the array, FALSE otherwise. */ function _skinr_in_multiarray($needle, $haystack) { if (is_array($haystack)) { // If $needle is in $haystack return TRUE. if (in_array($needle, $haystack)) { return TRUE; } // If $needle isn't in $haystack, then check each item in the array. foreach ($haystack as $haybale) { if (is_array($haybale) && _skinr_in_multiarray($needle, $haybale)) { return TRUE; } } } return FALSE; } /** * Returns an array of classes. * * @param $skin_options * An array containing the following keys: * - _options: An array of skin options keyed by their skin name. * - _additional: A string containing additional classes to apply. * * @todo Rename function to reflect new functionality. */ function skinr_flatten_skins_array($skin_options) { $skin_infos = skinr_get_skin_info(); $classes = array(); if (!empty($skin_options['_options'])) { foreach ($skin_options['_options'] as $skin_name => $options) { if (!is_array($options)) { $options = array($options); } foreach ($options as $option) { if (!empty($skin_infos[$skin_name]['options'][$option]['class'])) { $classes = array_merge($classes, $skin_infos[$skin_name]['options'][$option]['class']); } } } } if (!empty($skin_options['_additional'])) { $classes[] = $skin_options['_additional']; } return array_unique($classes); } // ------------------------------------------------------------------ // Rule functions. /** * Save a skinr rule object. * * @param $rule * A rule object. * * @return * The rule ID. */ function skinr_rule_save($rule) { drupal_write_record('skinr_rules', $rule, !empty($rule->rid) ? array('rid') : array()); return $rule->rid; } /** * Load a skinr rule object. * * @param $rid * (optional) The rule ID. * * @return * A rule object. If no $rid is specified an array of all rules will be * returned. */ function skinr_rule_load($rid = NULL) { $rids = (isset($rid) ? array($rid) : array()); $rules = skinr_rule_load_multiple($rids); return $rules ? reset($rules) : FALSE; } /** * Loads multiple skinr rule objects. * * @param $rids * An array of rule IDs. Optional. * @param $conditions * An array of conditions on the {skinr_rules} table in the form 'field' => * $value. * * @return * An array of rule objects indexed by rid. If $rids is not provided, all * rules are returned. */ function skinr_rule_load_multiple($rids = array(), $conditions = array()) { $rules = array(); $select = db_select('skinr_rules')->fields('skinr_rules'); if (!empty($rids)) { $select->condition('rid', $rids); } foreach ($conditions as $field => $condition) { $select->condition($field, $condition); } foreach ($select->execute() as $rule) { $rule->roles = unserialize($rule->roles); $rules[$rule->rid] = $rule; } return $rules; } /** * Delete a skinr rule object. * * @param $rid * The rule ID. */ function skinr_rule_delete($rid) { if ($rule = skinr_rule_load($rid)) { db_delete('skinr_rules') ->condition('rid', $rule->rid) ->execute(); db_delete('skinr') ->condition('module', 'page') ->condition('sid', $rule->rid) ->execute(); } } /** * Determine whether a rule is applies to the current page or not. * * @param $rid * The rule ID. * * @todo Rename this function to skinr_rule_is_visible(). */ 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. if (module_exists('php')) { $page_match = php_eval($rule->pages); } } } return $page_match; } return FALSE; } /** * Returns a list of extensions that implement this API version of Skinr. * * @return * An associative array whose keys are system names of extensions and whose * values are again associative arrays containing: * - type: Either 'module' or 'theme'. * - name: The system name of the extension. * - path: The path to the extension. * - directory: (optional) The sub-directory holding Skinr plugin files. * - ...: Any other properties defined by the module or theme. * * @todo Cache this. */ function skinr_implements() { $cache = &drupal_static(__FUNCTION__); if (!isset($cache)) { $cache = array(); // Collect hook_skinr_api_VERSION() module implementations. This will also // auto-load $module.skinr.inc files, which may contain skin/group hook // implementations (when not using the plugin system). $module_info = system_get_info('module'); foreach (module_implements('skinr_api_' . SKINR_VERSION) as $module) { // Ensure that $module and the extension type is registered. $cache[$module] = array( 'type' => 'module', 'name' => $module, 'version' => isset($module_info[$module]['version']) ? $module_info[$module]['version'] : NULL, ); // Check whether the hook returns any information. $function = $module . '_skinr_api_' . SKINR_VERSION; $info = $function(); if (isset($info) && is_array($info)) { $cache[$module] += $info; } // If the module specified a custom path, check whether it contains a // $module.skinr.inc file and auto-load it. module_implements() only // auto-loads $module.skinr.inc in a module's root folder. if (isset($cache[$module]['path'])) { $file = DRUPAL_ROOT . '/' . $cache[$module]['path'] . '/' . $module . '.skinr.inc'; if (file_exists($file)) { require_once $file; } } // Populate defaults. $cache[$module] += array( 'path' => drupal_get_path('module', $module), 'directory' => NULL, ); } // Collect the equivalent of hook_skinr_api_VERSION() implementations in // themes. The theme system only initializes one theme (and optionally its // base themes) for the current request, and the phptemplate engine only // loads template.php during theme initialization. Furthermore, template.php // is a custom concept of the phptemplate engine and does not exist for // other theme engines. Since we are interested in all existing // implementations of all enabled themes, the equivalent of the module hook // is a theme .info file property 'skinr' that has the sub-keys 'api' and // optionally 'directory' defined. // Account for all enabled themes and (any recursive) base themes of them, // regardless of whether base themes are enabled. $all_themes = list_themes(); $themes = array(); // Additionally record the base themes and sub themes of each theme, in // order to apply inheritance rules elsewhere. Do not assign these variables // as properties on the theme objects themselves, since all objects are // pointers (much like references) in PHP 5, so our properties would be // visible for everyone else who calls list_themes(). $base_themes = array(); $sub_themes = array(); foreach ($all_themes as $name => $theme) { // If the theme is enabled, add it to the stack. if (!empty($theme->status)) { $themes[$name] = $theme; // Find and add all base themes of the enabled theme to the stack. // @see drupal_theme_initialize() $sub_theme_name = $name; while ($name && isset($all_themes[$name]->base_theme)) { // Record the sub theme for the base theme. $sub_themes[$all_themes[$name]->base_theme][$name] = $name; // Add the base theme to the stack. $name = $all_themes[$name]->base_theme; $themes[$name] = $all_themes[$name]; // Record the base theme for the original sub theme. $base_themes[$sub_theme_name][$name] = $name; } } } foreach ($themes as $name => $theme) { if (isset($theme->info['skinr']['api']) && $theme->info['skinr']['api'] == SKINR_VERSION) { // Ensure that the theme name and the extension type is registered. $cache[$name] = array( 'type' => 'theme', 'name' => $name, 'version' => isset($theme->info['version']) ? $theme->info['version'] : NULL, 'base themes' => isset($base_themes[$name]) ? $base_themes[$name] : array(), 'sub themes' => isset($sub_themes[$name]) ? $sub_themes[$name] : array(), ); // Add any additional information that has been registered. $cache[$name] += $theme->info['skinr']; // Populate defaults. $cache[$name] += array( 'path' => drupal_get_path('theme', $name), // Since themes cannot do anything else than registering skins and // groups, we default to the sub-directory 'skins'. 'directory' => 'skins', ); // Lastly, for API consistency with modules, check whether the theme // contains a $theme.skinr.inc file and auto-load it, if any. $file = DRUPAL_ROOT . '/' . $cache[$name]['path'] . '/' . $name . '.skinr.inc'; if (file_exists($file)) { require_once $file; } } } } return $cache; } /** * Includes $extension.skinr.inc files of extensions compatible with this version of Skinr. * * @todo Shoot me. Twice. */ function skinr_load_includes() { foreach (skinr_implements() as $extension) { $file = DRUPAL_ROOT . '/' . $extension['path'] . '/' . $extension['name'] . '.skinr.inc'; if (file_exists($file)) { require_once $file; } } } /** * Includes Skinr plugin files for an extension, if any. * * @param $extension * The API information for an extension, as returned by skinr_implements(). */ function skinr_load_plugins($extension) { static $loaded = array(); // If plugins have already been loaded for this extension, return them. if (isset($loaded[$extension['name']])) { return $loaded[$extension['name']]; } $loaded[$extension['name']] = array(); // If the extension defines a plugin directory, scan its plugins. if (isset($extension['directory'])) { $dir = DRUPAL_ROOT . '/' . $extension['path'] . '/' . $extension['directory']; $mask = '@^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.inc$@'; $loaded[$extension['name']] = file_scan_directory($dir, $mask, array( 'key' => 'name', 'recurse' => TRUE, 'min_depth' => 1, 'callback' => 'skinr_include_once', )); } return $loaded[$extension['name']]; } /** * file_scan_directory() callback wrapper around include_once. * * include_once is a PHP construct, not a function, so it cannot be invoked * directly as 'callback' in file_scan_directory(). */ function skinr_include_once($file) { include_once $file; } // ----------------------------------------------------------------------- // Skinr data handling functions. /** * Validate a skinr object. * * @param $skin * A skin object. * * @return * TRUE on success, FALSE on failure. */ function skinr_skin_validate(&$skin) { if (!isset($skin->theme) || !isset($skin->module) || !isset($skin->sid) || !isset($skin->skins)) { return FALSE; } if (!isset($skin->settings)) { $skin->settings = array(); } if (!is_array($skin->skins) || !is_array($skin->settings)) { return FALSE; } // Strip empty skins. $skin->skins = _skinr_array_strip_empty($skin->skins); return TRUE; } /** * Save a skin object. * * @param $skin * A skin object. * * @return * TRUE on success, FALSE on failure. */ function skinr_skin_save($skin) { // Make sure we're getting valid data. if (!skinr_skin_validate($skin)) { return FALSE; } if (empty($skin->skins) && empty($skin->settings)) { // Delete the db entry if it exists. db_delete('skinr') ->condition('theme', $skin->theme) ->condition('module', $skin->module) ->condition('sid', $skin->sid) ->execute(); } else { // Let's save the data. if (skinr_skin_load($skin->theme, $skin->module, $skin->sid) !== FALSE) { // Record exists, so let's update. drupal_write_record('skinr', $skin, array('theme', 'module', 'sid')); } else { // Insert a new record. drupal_write_record('skinr', $skin); } } return TRUE; } /** * Delete a skin object. * * @param $theme * The theme this skin applies to. If no theme name is provided, the * current theme will be used. * @param $module * The module. * @param $sid * The element ID. */ function skinr_skin_delete($theme = NULL, $module = NULL, $sid = NULL) { node_delete_multiple(array(array($theme, $module, $sid))); } /** * Delete multiple skin objects. * * @param $arguments * An array of arrays containing the following arguments: * - $theme * - $module * - $sid * * @see skinr_skin_delete(). * * @todo Make this function functional. */ function skinr_skin_delete_multiple($arguments) { } /** * Retrieves a stored skin from the database. * * @param $theme * The theme of the skin. Defaults to the current theme. * @param $module * The module of the skin. * @param $sid * The element ID of the skin. * * @return * A skin object if both $module and $sid are specified. An array of skins * if only $module is specified. An array of all skins for a theme if neither * $module nor $sid is specified. FALSE on failure. * * @todo Rename $skin->skins to $skin->options throughout the module. */ function skinr_skin_load($theme = NULL, $module = NULL, $sid = NULL) { $skins = &drupal_static(__FUNCTION__, array()); if (!isset($theme)) { $theme = skinr_current_theme(); } // @todo This condition is always FALSE when no $sid is passed. if (!isset($skins[$theme][$module][$sid])) { $skins += array($theme => array()); if (isset($module)) { $skins[$theme] += array($module => array()); } $query = db_select('skinr', 's') ->fields('s', array('theme', 'module', 'sid', 'settings', 'skins')); if (isset($theme)) { $query->condition('theme', $theme); } if (isset($module)) { $query->condition('module', $module); } if (isset($sid)) { $query->condition('sid', $sid); } foreach ($query->execute() as $skin) { $skin->settings = unserialize($skin->settings); $skin->skins = unserialize($skin->skins); $skins[$skin->theme][$skin->module][$skin->sid] = $skin; } } // Return all skins for the passed theme. if (!isset($module) && !isset($sid)) { if (isset($skins[$theme])) { return $skins[$theme]; } } // Return all skins for the passed module. elseif (!isset($sid)) { if (isset($skins[$theme][$module])) { return $skins[$theme][$module]; } } // Return the requested skin. elseif (isset($skins[$theme][$module][$sid])) { return $skins[$theme][$module][$sid]; } return FALSE; } /** * Load multiple skin objects. * * @param $arguments * An array of arrays containing the following arguments: * - $theme * - $module * - $sid * * @see skinr_skin_load(). * * @todo Make this function functional. * @todo Look at using hook_entity_info() and entity_load(). */ function skinr_skin_load_multiple($arguments) { } /** * Helper function to remove empty skins from an array. * * @param $array * A single or multi-dimensional array to strip of empty values. * * @return * An array stripped of empty values. */ 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 $exclude_admin_theme * Optional. Set to TRUE to exclude the admin theme from possible themes to * return. * * @return * The current theme name. */ function skinr_current_theme($exclude_admin_theme = FALSE) { global $user, $custom_theme; if (!empty($user->theme) && drupal_theme_access($user->theme)) { $current_theme = $user->theme; } elseif (!empty($custom_theme) && drupal_theme_access($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', 'bartik'); } return $current_theme; } /** * Prepare the default status for a skin. * * @param $skin_info * Information about a registered skin. * * @return * An array of default statuses for each enabled theme. */ function skinr_skin_info_status_default($skin_info) { $status = array(); // Retrieve the explicit default status of the registering theme for itself. $base_theme_status = NULL; if (isset($skin_info['status'][$skin_info['source']['name']])) { $base_theme_status = $skin_info['status'][$skin_info['source']['name']]; } // Retrieve the sub themes of the base theme that registered the skin. $sub_themes = array(); if (isset($skin_info['source']['sub themes'])) { $sub_themes = $skin_info['source']['sub themes']; } $themes = list_themes(); foreach ($themes as $name => $theme) { if (!$theme->status) { continue; } // If this theme is a sub theme of the theme that registered the skin, check // whether we need to inherit the status of the base theme to the sub theme. // This is the case when a skin of a base theme enables itself for the base // theme (not knowing about potential sub themes). if (isset($base_theme_status) && isset($sub_themes[$name])) { $status[$name] = $base_theme_status; } // Apply global default. $status += array($name => $skin_info['default status']); } // Lastly, apply all explicit defaults. $status = array_merge($status, $skin_info['status']); return $status; } /** * Helper function to prepend a path to an array of stylesheet or script filenames. * * If the url is absolute (e.g. the url start with 'http://' or 'https://') * the path does not get prepended. * * @param $files * A an array of filenames that need the path prepended. * @todo Adjust docs to account for arrays instead of filenames. * @param $path * The path to prepend. */ function _skinr_add_path_to_files(&$files, $path) { foreach ($files as $key => $file) { if (is_array($file)) { if (strpos($file[0], 'http://') === 0 || strpos($file[0], 'https://') === 0 ) { continue; } $files[$key][0] = $path . '/' . $file[0]; } else { if (strpos($file, 'http://') === 0 || strpos($file, 'https://') === 0) { continue; } $files[$key] = $path . '/' . $file; } } } /** * Parse a skin_infos array as returned from a skins plugin. * * This function inserts any missing defaults and updates the stylesheet and * script paths to be relative to Drupal's root. * * @param $skin_infos * A skins array as returned from a skins plugin. * @param $source * An associative array containing information about the source of the skin. * See skinr_implements() for details. * * @todo Merge into skinr_get_skin_info() and remove this function. */ function skinr_skin_info_process(&$skin_infos, $source) { foreach ($skin_infos as $skin_name => $skin_info) { // Populate default properties. $skin_infos[$skin_name] += array( 'name' => '', 'title' => '', 'type' => 'checkboxes', 'description' => '', 'group' => 'general', 'theme hooks' => array('*'), 'attached' => array(), 'options' => array(), 'weight' => NULL, 'default status' => 0, 'status' => array(), ); // Merge in name. $skin_infos[$skin_name]['name'] = $skin_name; // Merge in source information. $skin_infos[$skin_name]['source'] = $source; // Merge in default status for all themes. $skin_infos[$skin_name]['status'] = skinr_skin_info_status_default($skin_infos[$skin_name]); // Add path to stylesheets. if (isset($skin_infos[$skin_name]['attached']['css'])) { _skinr_add_path_to_files($skin_infos[$skin_name]['attached']['css'], $source['path']); } // Add path to scripts. if (isset($skin_infos[$skin_name]['attached']['js'])) { _skinr_add_path_to_files($skin_infos[$skin_name]['attached']['js'], $source['path']); } foreach ($skin_infos[$skin_name]['options'] as $option_name => $option) { // Add path to stylesheets. if (isset($option['attached']['css'])) { _skinr_add_path_to_files($skin_infos[$skin_name]['options'][$option_name]['attached']['css'], $source['path']); } // Add path to scripts. if (isset($option['attached']['js'])) { _skinr_add_path_to_files($skin_infos[$skin_name]['options'][$option_name]['attached']['js'], $source['path']); } // Validate class by running it through drupal_html_class(). if (!is_array($skin_infos[$skin_name]['options'][$option_name]['class'])) { $skin_infos[$skin_name]['options'][$option_name]['class'] = array($skin_infos[$skin_name]['options'][$option_name]['class']); } foreach ($skin_infos[$skin_name]['options'][$option_name]['class'] as $key => $class) { $skin_infos[$skin_name]['options'][$option_name]['class'][$key] = drupal_html_class($class); } } } } /** * Retrieves all skins registered by modules and themes. * * @return * An array of skins. */ function skinr_get_skin_info() { $skin_info = &drupal_static(__FUNCTION__); if (!isset($skin_info)) { if ($cached = cache_get('skinr_skin_info')) { $skin_info = $cached->data; return $skin_info; } $skin_info = array(); foreach (skinr_implements() as $name => $extension) { $hooks = array( "{$name}_skinr_skin_info" => $extension, ); // Load the extension's plugins, if any. if ($files = skinr_load_plugins($extension)) { // The base path for plugins is the directory defined by the extension. $dir = $extension['path'] . '/' . $extension['directory']; foreach ($files as $plugin => $file) { $hooks["{$name}_skinr_skin_{$plugin}_info"] = array( // The source path for a plugin is the plugin directory. 'path' => $dir . '/' . basename(dirname($file->uri)), ) + $extension; } } foreach ($hooks as $function => $source) { if (function_exists($function)) { $extension_info = $function(); if (isset($extension_info) && is_array($extension_info)) { // Prepare the skin information. skinr_skin_info_process($extension_info, $source); $skin_info += $extension_info; } } } } // Allow modules to alter registered skin information. drupal_alter('skinr_skin_info', $skin_info); cache_set('skinr_skin_info', $skin_info); } return $skin_info; } /** * Retrieves all skin groups registered by modules and themes. * * @return * An array of groups. */ function skinr_get_group_info() { $group_info = &drupal_static(__FUNCTION__); if (!isset($group_info)) { if ($cached = cache_get('skinr_group_info')) { $group_info = $cached->data; return $group_info; } $group_info = array(); foreach (skinr_implements() as $name => $extension) { $hooks = array( "{$name}_skinr_group_info" => $extension, ); // Load the extension's plugins, if any. if ($files = skinr_load_plugins($extension)) { // The base path for plugins is the directory defined by the extension. $dir = $extension['path'] . '/' . $extension['directory']; foreach ($files as $plugin => $file) { $hooks["{$name}_skinr_group_{$plugin}_info"] = array( // The source path for a plugin is the plugin directory. 'path' => $dir . '/' . basename(dirname($file->uri)), ) + $extension; } } foreach ($hooks as $function => $source) { if (function_exists($function)) { $extension_info = $function(); if (isset($extension_info) && is_array($extension_info)) { // Prepare the skin group information. foreach ($extension_info as &$group) { $group += array( 'title' => '', 'description' => '', 'weight' => 0, ); } $group_info += $extension_info; } } } } // Allow modules to alter groups through hook_skinr_group_info_alter(). drupal_alter('skinr_group_info', $group_info); cache_set('skinr_group_info', $group_info); } return $group_info; } /** * Fetch Skinr configuration data from functionality plugins. * * @return * An array of all configuration data. */ function skinr_get_config_info() { $config_info = &drupal_static(__FUNCTION__); if (!isset($config)) { if ($cached = cache_get('skinr_config_info')) { $config_info = $cached->data; return $config_info; } $config_info = array(); foreach (skinr_implements() as $name => $extension) { $function = "{$name}_skinr_config_info"; if (function_exists($function)) { $extension_info = $function(); if (isset($extension_info) && is_array($extension_info)) { $config_info = array_merge_recursive($config_info, $extension_info); } } } // Allow modules to alter config info via hook_skinr_config_info_alter(). drupal_alter('skinr_config_info', $config_info); cache_set('skinr_config_info', $config_info); } return $config_info; } /** * Prepare default configuration data for modules. * * @todo Search and destroy. */ function skinr_config_info_default() { return array( 'access_handler' => 'skinr_access_handler', 'index_handler' => 'skinr_index_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, ); } /** * Execute a module's data handler. * * @param $type * The type of handler to execute. Possible values: * - 'access_handler': * - 'contextual_links': * - 'data_handler': * - 'form_index_handler': * - 'preprocess_index_handler': * - 'preprocess_hook_callback': * - 'submit_handler': * @param $op * For 'access_handler' the possible values are 'edit skin settings' * and 'edit advanced skin settings'. * For 'contextual_links' an empty string is passed. * For 'data_handler' the possible values are 'form' and 'submit'. * For 'form_index_handler' the possible values are 'form' and 'submit'. * For 'preprocess_index_handler' the possible values are 'preprocess'. * For 'preprocess_hook_callback' an empty string is passed. * For 'submit_handler' an empty string is passed. * @param $handler * The function name for this handler as gotten from skinr_fetch_config(). * @param $a3 * For 'access_handler', passes in the $form parameter as provided to a form * function. * For 'contextual_links', passes in the $variables parameter from * skinr_preprocess(). * For 'data_handler', passes in the $form parameter from hook_form_submit(). * For 'form_index_handler': * - For $op 'form', passes in the $form parameter from hook_form_alter(). * - For $op 'submit', passes in the $form parameter from hook_form_submit(). * For 'preprocess_index_handler', passes in the $variables parameter from * module_preprocess(). * For 'preprocess_hook_callback', passes in the $form parameter from * hook_form_alter(). * For 'submit_handler', passes in the $form parameter from hook_form_alter(). * * @param $a4 * For 'access_handler', passes in the $form_state array as provided to a * form function. * For 'data_handler', passes in the $form_state parameter form * hook_form_submit(). * For 'form_index_handler': * - For $op 'form', passes in the $form_state parameter from * hook_form_alter(). * - For $op 'submit', passes in the $form_state parameter from * hook_form_submit(). * For 'preprocess_hook_callback', passes in the $form_state parameter from * hook_form_alter(). * For 'submit_handler', passes in the $form_state parameter from * hook_form_alter(). * @param $a5 * For 'data_handler', passes in the module that is currently being processed. * For 'submit_handler', passes in the module that is currently being * processed. * @param $a6 * For 'data_handler', passes in the settings from hook_skinr_config() for * the form that's currently being processed. * For 'submit_handler', passes in the settings from hook_skinr_config() for * the form that's currently being processed. * @param $a7 */ function skinr_handler($type, $op, $handler, &$a3, $a4 = NULL, $a5 = NULL, $a6 = NULL, $a7 = NULL) { if (is_callable($handler)) { switch ($type) { case 'contextual_links': 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); } } } /** * Implements hook_modules_enabled(). */ function skinr_modules_enabled() { skinr_cache_reset(); } /** * Implements hook_modules_disabled(). */ function skinr_modules_disabled() { skinr_cache_reset(); } /** * Implements hook_themes_enabled(). */ function skinr_themes_enabled() { skinr_cache_reset(); } /** * Implements hook_themes_disabled(). */ function skinr_themes_disabled() { skinr_cache_reset(); }