skinr.module in Skinr 7.2
Same filename and directory in other branches
Handles core Skinr functionality.
File
skinr.moduleView source
<?php
/**
* @file
* Handles core Skinr functionality.
*/
/**
* The Skinr API version.
*/
define('SKINR_VERSION', 2);
/**
* A flag used to let us know if an object is in the database.
*/
define('SKINR_STORAGE_IN_DATABASE', 0);
define('SKINR_STORAGE_IN_CODE', 1);
define('SKINR_STORAGE_IN_CODE_OVERRIDDEN', 2);
/**
* Implements 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;
}
}
/**
* Implements hook_hook_info().
*/
function skinr_hook_info() {
$hooks = array(
'skinr_api_2',
'skinr_elements',
'skinr_group_info',
'skinr_group_info_alter',
'skinr_skin_info',
'skinr_skin_info_alter',
'skinr_theme_hooks',
'skinr_theme_hooks_alter',
);
$hooks = array_fill_keys($hooks, array(
'group' => 'skinr',
));
$hooks['skinr_skin_defaults'] = array(
'group' => 'skinr_default',
);
return $hooks;
}
/**
* Clears cached Skinr information.
*/
function skinr_cache_reset() {
cache_clear_all('skinr_', 'cache', TRUE);
}
/**
* Implements hook_preprocess().
*
* @todo Optimize this function by removing dependencies on
* skinr_get_skin_info() and similar resource heavy functions.
* @todo Account for Drupal's caching being enabled and make it work.
*/
function skinr_preprocess(&$variables, $hook) {
// Fix for update script.
if (defined('MAINTENANCE_MODE')) {
return;
}
$data =& drupal_static(__FUNCTION__);
// Caching the data returned from the following functions is reported to
// improve performance.
if (!isset($data)) {
$data['current_theme'] = skinr_current_theme();
$data['skin_info'] = skinr_get_skin_info();
$data['theme_registry'] = theme_get_registry();
$data['skip_cache'] = FALSE;
$implementations = module_implements('skinr_preprocess_alter');
// skinr_panels is special case that only runs when skinr_context is enabled.
if (count($implementations) > 0 && $implementations[0] !== 'skinr_panels') {
// Skip caching whenever a module implements skinr_preprocess_alter.
$data['skip_cache'] = TRUE;
}
}
$original_hook = isset($data['theme_registry'][$hook]['original hook']) ? $data['theme_registry'][$hook]['original hook'] : $hook;
// An array of $elements based on $module and $original_hook, derived from $variables.
$array_elements = skinr_invoke_all('skinr_elements', $variables, $original_hook, 'preprocess');
$timeit = FALSE;
if (is_array($array_elements) && isset($array_elements[$original_hook]) && in_array('system__navigation', $array_elements[$original_hook])) {
$timeit = TRUE;
}
if ($timeit) {
timer_start(__FUNCTION__ . '__loop');
}
foreach ($array_elements as $module => $elements) {
$applied_skins = array();
foreach ($elements as $element) {
if ($timeit) {
timer_start(__FUNCTION__ . '__cache');
}
$cid = 'skinr_preprocess:' . $module . ':' . $element . ':' . $data['current_theme'];
if (!$data['skip_cache'] && ($cached = cache_get($cid))) {
// This type of caching is incompatible with skinr_context.
$applied_skins = $cached->data;
}
else {
// Get a list of skin configuration IDs to pass to
// skinr_skin_load_multiple().
$params = array(
'theme' => $data['current_theme'],
'module' => $module,
'element' => $element,
'status' => 1,
);
$sids = skinr_skin_get_sids($params);
$skins = !empty($sids) ? skinr_skin_load_multiple($sids) : array();
// Invoke hook_skinr_preprocess_alter() in all modules.
$context = array(
'hook' => $hook,
'variables' => &$variables,
'theme' => $data['current_theme'],
'module' => $module,
'elements' => $elements,
);
drupal_alter('skinr_preprocess', $skins, $context);
$applied_skins = array();
foreach ($skins as $skin) {
$applied_skins = array(
$skin->skin => $skin->options,
) + $applied_skins;
}
// Cache data.
if (!$data['skip_cache']) {
cache_set($cid, $applied_skins);
}
}
}
// Use drupal_process_attached() to add attachements such as JS and CSS.
if (!empty($applied_skins)) {
foreach ($applied_skins as $skin_name => $skin_options) {
// Special case for _additional.
if ($skin_name == '_additional') {
continue;
}
// Make sure this skin is enabled for the current theme.
if (isset($data['skin_info'][$skin_name]['attached'])) {
$elements = array(
'#attached' => $data['skin_info'][$skin_name]['attached'],
);
drupal_process_attached($elements);
}
if (!is_array($skin_options)) {
$skin_options = array(
$skin_options,
);
}
foreach ($skin_options as $skin_option) {
if (isset($data['skin_info'][$skin_name]['options'][$skin_option]['attached'])) {
$elements = array(
'#attached' => $data['skin_info'][$skin_name]['options'][$skin_option]['attached'],
);
drupal_process_attached($elements);
}
}
}
$variables['classes_array'] = array_merge($variables['classes_array'], skinr_flatten_skins_array($applied_skins));
}
}
}
/**
* Returns an array of classes.
*
* @param $skin_options
* An array of skin options keyed by their skin name. The key '_additional'
* is reserved for additional classes entered by the user.
*
* @todo Optimize this function by removing dependencies on the resource heavy
* skinr_get_skin_info() function.
* @todo Rename function to reflect new functionality.
*/
function skinr_flatten_skins_array($skin_options) {
$skin_info = skinr_get_skin_info();
$classes = array();
foreach ($skin_options as $skin_name => $options) {
if ($skin_name == '_additional') {
$classes = array_merge($classes, $options);
}
else {
foreach ($options as $option) {
if (!empty($skin_info[$skin_name]['options'][$option]['class'])) {
$classes = array_merge($classes, $skin_info[$skin_name]['options'][$option]['class']);
}
}
}
}
return array_unique($classes);
}
/**
* 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.
*/
function skinr_implements_api() {
// All themes are disabled while running update script so theme skins are not
// cached. Don't cache to prevent this.
if (defined('MAINTENANCE_MODE')) {
return array();
}
$cache =& drupal_static(__FUNCTION__);
if (!isset($cache)) {
if ($cached = cache_get('skinr_implements_api')) {
$cache = $cached->data;
return $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 = $cache[$module]['path'] . '/' . $module . '.skinr.inc';
if (file_exists(DRUPAL_ROOT . '/' . $file)) {
$cache[$module]['include file'] = $file;
}
}
else {
// If there is a $module.skinr.inc in the module's root, it gets
// auto-loaded for any hooks. But if a skin defined thering contains a
// custom 'form callback' function, we'll need to load it manually. So
// store the file's info.
$file = drupal_get_path('module', $module) . '/' . $module . '.skinr.inc';
if (file_exists(DRUPAL_ROOT . '/' . $file)) {
$cache[$module]['include file'] = $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 = $cache[$name]['path'] . '/' . $name . '.skinr.inc';
if (file_exists(DRUPAL_ROOT . '/' . $file)) {
$cache[$name]['include file'] = $file;
}
}
}
cache_set('skinr_implements_api', $cache);
}
return $cache;
}
/**
* Determine whether a module implements a hook.
*
* Replacement for module_hook() that only invokes modules that implement
* the current version of Skinr API. It also supports $module.skinr.inc files
* in themes and custom paths.
*
* @param $module
* The name of the module (without the .module extension).
* @param $hook
* The name of the hook (e.g. "skinr_skin_info" or "skinr_theme_hooks").
*
* @return
* TRUE if the module is both installed and enabled, and the hook is
* implemented in that module.
*/
function skinr_hook($module, $hook) {
$function = $module . '_' . $hook;
if (function_exists($function)) {
return TRUE;
}
// If the hook implementation does not exist, check whether it may live in an
// include file in a custom path.
$extensions = skinr_implements_api();
if (isset($extensions[$module])) {
$extension = $extensions[$module];
if (isset($extension['include file'])) {
// The module specified a custom path. module_hook() only auto-loads
// $module.skinr.inc in a module's root folder.
skinr_load_include($extension['include file']);
if (function_exists($module . '_' . $hook)) {
return TRUE;
}
}
else {
// Run through module_hook() to auto-load $module.skinr.inc from a
// non-custom path.
if (module_hook($module, $hook)) {
return TRUE;
}
}
}
return FALSE;
}
/**
* Determine which modules are implementing a hook.
*
* Replacement for module_implements() that only invokes modules that implement
* the current version of Skinr API. It also supports $module.skinr.inc files
* in themes and custom paths.
*
* @param $hook
* The name of the hook (e.g. "skinr_skin_info" or "skinr_theme_hooks").
*
* @return
* An array with the names of the modules which are implementing this hook.
*
* @see skinr_exit()
*/
function skinr_implements($hook) {
$implementations =& drupal_static(__FUNCTION__, array());
// Fetch implementations from cache.
if (empty($implementations)) {
$implementations = cache_get('skinr_implements', 'cache_bootstrap');
if ($implementations === FALSE) {
$implementations = array();
}
else {
$implementations = $implementations->data;
}
}
if (!isset($implementations[$hook])) {
$implementations['#write_cache'] = TRUE;
$extensions = skinr_implements_api();
$implementations[$hook] = array();
foreach ($extensions as $module => $extension) {
if (isset($extension['include file'])) {
// The module specified a custom path. module_implements() and
// module_hook() only auto-load $module.skinr.inc in a module's
// root folder.
$include_file = skinr_load_include($extension['include file']);
if (function_exists($module . '_' . $hook)) {
$implementations[$hook][$module] = $include_file ? $extension['include file'] : FALSE;
}
}
else {
// Run through module_hook() to auto-load $module.skinr.inc from a
// non-custom path.
if (module_hook($module, $hook)) {
$implementations[$hook][$module] = FALSE;
}
}
}
// Allow modules to change the weight of specific implementations but avoid
// an infinite loop.
if ($hook != 'skinr_implements_alter') {
drupal_alter('skinr_implements', $implementations[$hook], $hook);
}
}
else {
foreach ($implementations[$hook] as $module => $file) {
if ($file) {
skinr_load_include($file);
}
else {
module_hook($module, $hook);
}
// It is possible that a module removed a hook implementation without the
// implementations cache being rebuilt yet, so we check whether the
// function exists on each request to avoid undefined function errors.
// Since module_hook() may needlessly try to load the include file again,
// function_exists() is used directly here.
if (!function_exists($module . '_' . $hook)) {
// Clear out the stale implementation from the cache and force a cache
// refresh to forget about no longer existing hook implementations.
unset($implementations[$hook][$module]);
$implementations['#write_cache'] = TRUE;
}
}
}
return array_keys($implementations[$hook]);
}
/**
* Implements hook_exit().
*
* @see module_implements_write_cache()
*/
function skinr_exit($destination = NULL) {
$implementations =& drupal_static('skinr_implements');
// Check whether we need to write the cache. We do not want to cache hooks
// which are only invoked on HTTP POST requests since these do not need to be
// optimized as tightly, and not doing so keeps the cache entry smaller.
if (isset($implementations['#write_cache']) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD')) {
unset($implementations['#write_cache']);
cache_set('skinr_implements', $implementations, 'cache_bootstrap');
}
}
/**
* Invoke a hook in all enabled modules and themes that implement it.
*
* Replacement for module_invoke_all() that only invokes modules that implement
* the current version of Skinr API. It also supports $module.skinr.inc files
* in themes and custom paths.
*
* @param $hook
* The name of the hook to invoke.
* @param ...
* Arguments to pass to the hook.
*
* @return
* An array of return values of the hook implementations. If modules return
* arrays from their implementations, those are merged into one array.
*/
function skinr_invoke_all($hook) {
$args = func_get_args();
// Remove $hook from the arguments.
unset($args[0]);
$return = array();
foreach (skinr_implements($hook) as $module) {
$function = $module . '_' . $hook;
if (function_exists($function)) {
$result = call_user_func_array($function, $args);
if (isset($result) && is_array($result)) {
$return = array_merge_recursive($return, $result);
}
elseif (isset($result)) {
$return[] = $result;
}
}
}
return $return;
}
/**
* Loads a $module.skinr.inc include file.
*/
function skinr_load_include($file) {
if (is_file($file)) {
include_once $file;
return $file;
}
return FALSE;
}
/**
* Includes Skinr plugin files for an extension, if any.
*
* @param $extension
* The API information for an extension, as returned by skinr_implements_api().
*/
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 (empty($skin->theme) || empty($skin->module) || empty($skin->element) || empty($skin->skin) || empty($skin->options)) {
return FALSE;
}
if (!is_array($skin->options)) {
return FALSE;
}
// Strip empty skins.
$skin->options = _skinr_array_strip_empty($skin->options);
if (empty($skin->options)) {
return FALSE;
}
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;
}
// Load the stored skin configuration object, if any.
if (!empty($skin->sid)) {
if (!isset($skin->original)) {
// Load an uncached version of the skin configuration object.
$skin->original = skinr_skin_load_unchanged($skin->sid);
}
}
// Let modules modify the node before it is saved to the database.
module_invoke_all('skinr_skin_presave', $skin);
if (!empty($skin->sid)) {
// Record exists, so let's update.
$status = drupal_write_record('skinr_skins', $skin, 'sid');
module_invoke_all('skinr_skin_update', $skin);
}
else {
// Assign it a UUID if none is set.
if (empty($skin->uuid)) {
if (!module_exists('uuid')) {
module_load_include('inc', 'skinr', 'skinr.uuid');
}
$skin->uuid = uuid_generate();
}
// Insert a new record.
$status = drupal_write_record('skinr_skins', $skin);
module_invoke_all('skinr_skin_insert', $skin);
}
// Clear internal properties.
unset($skin->original);
// Clear the static loading cache.
// @todo Once we have a more granular reset for skinr_skin_load_multiple(), we
// need to use it here.
drupal_static_reset('skinr_skin_load_multiple');
// Clear preprocess cache.
cache_clear_all('skinr_preprocess:' . $skin->module . ':' . $skin->element . ':', 'cache', TRUE);
return $status;
}
/**
* Delete a skin object.
*
* @param $sid
* The skin configuration ID.
*/
function skinr_skin_delete($sid) {
skinr_skin_delete_multiple(array(
$sid,
));
}
/**
* Delete multiple skin configuration objects.
*
* @param $sids
* An array of skin configuration IDs.
*/
function skinr_skin_delete_multiple($sids) {
$transaction = db_transaction();
if (!empty($sids)) {
$skins = skinr_skin_load_multiple($sids);
try {
foreach ($skins as $sid => $skin) {
module_invoke_all('skinr_skin_delete', $skin);
}
// Delete after calling hooks so that they can query node tables as needed.
db_delete('skinr_skins')
->condition('sid', $sids, 'IN')
->execute();
} catch (Exception $e) {
$transaction
->rollback();
watchdog_exception('skinr', $e);
throw $e;
}
// Clear the skinr_skin_load_multiple cache.
drupal_static_reset('skinr_skin_load_multiple');
}
}
/**
* Load a skin configuration object from the database.
*
* @param $sid
* The skin configuration ID.
*
* @return
* A fully-populated skin configuration object.
*/
function skinr_skin_load($sid = NULL) {
$sids = isset($sid) ? array(
$sid,
) : array();
$skin = skinr_skin_load_multiple($sids);
return $skin ? reset($skin) : FALSE;
}
/**
* Get skin configuration IDs.
*/
function skinr_skin_uuid_to_sid($uuid) {
$sids =& drupal_static(__FUNCTION__, array());
if (!isset($sids[$uuid])) {
$sids[$uuid] = db_query("SELECT sid FROM {skinr_skins} WHERE uuid = :uuid", array(
':uuid' => $uuid,
))
->fetchField();
}
return $sids[$uuid];
}
/**
* Get skin configuration IDs.
*/
function skinr_skin_sid_to_uuid($sid) {
$uuids =& drupal_static(__FUNCTION__, array());
if (!isset($uuids[$sid])) {
$uuids[$sid] = db_query("SELECT uuid FROM {skinr_skins} WHERE sid = :sid", array(
':sid' => $sid,
))
->fetchField();
}
return $uuids[$sid];
}
/**
* Load a skin configuration object from the database using UUID.
*
* @param $uuid
* The UUID of the skin configuration to load.
*
* @return
* A fully-populated skin configuration object.
*/
function skinr_skin_load_by_uuid($uuid) {
if (!($sid = skinr_skin_uuid_to_sid($uuid))) {
return FALSE;
}
// Run this through skinr_skin_load_multiple() to preserve caching.
$skin = skinr_skin_load_multiple(array(
$sid,
));
return $skin ? reset($skin) : FALSE;
}
/**
* Load skin configuration objects from the database.
*
* This function should be used whenever you need to load more than one skin
* configuration from the database. Skin configurations are loaded into memory
* and will not require database access if loaded again during the same page
* request.
*
* @see skinr_skin_get_sids()
*
* @param $sids
* An array of skin configuration IDs.
*
* @return
* An array of skin configuration objects indexed by sid.
*/
function skinr_skin_load_multiple($sids = array()) {
// @todo Do we want to write a more granular cache reset?
$skins =& drupal_static(__FUNCTION__, array());
// Create a new variable which is either a prepared version of the $sids
// array for later comparison with cached skin configuration objects, or FALSE
// if no $sids were passed. The $sids array is reduced as items are loaded
// from cache, and we need to know if it's empty for this reason to avoid
// querying the database when all requested skin configuration objects are
// loaded from cache.
$passed_sids = !empty($sids) ? array_flip($sids) : FALSE;
if ($passed_sids) {
$sids = array_keys(array_diff_key($passed_sids, $skins));
}
// Load any remaining skin configurations from the database. This is the
// case if $sids is set to FALSE (so we load all skins), or if there are any
// sids left to load.
if ($sids === FALSE || $sids) {
// Build the query.
$query = db_select('skinr_skins', 's')
->fields('s', array(
'sid',
'uuid',
'theme',
'module',
'element',
'skin',
'options',
'status',
));
if ($sids !== FALSE) {
$query
->condition('sid', $sids);
}
$queried_skins = $query
->execute()
->fetchAllAssoc('sid');
foreach ($queried_skins as $sid => $skin) {
// Unserialize options array.
$queried_skins[$sid]->options = unserialize($skin->options);
// Let modules modify the skin configurations.
module_invoke_all('skinr_skin_load', $queried_skins[$sid]);
}
$skins += $queried_skins;
}
// Ensure that the returned array is ordered the same as the original
// $sids array if this was passed in and remove any invalid sids.
if ($passed_sids) {
// Remove any invalid sids from the array.
$passed_sids = array_intersect_key($passed_sids, $skins);
$return = array();
foreach ($passed_sids as $sid => $ignore) {
$return[$sid] = $skins[$sid];
}
}
else {
$return = $skins;
}
return $return;
}
/**
* Load an uncached version of a skin configuration object.
*
* @param $sid
* The skin configuration ID.
*
* @return
* A fully-populated skin configuration object.
*/
function skinr_skin_load_unchanged($sid) {
// Load an uncached version of the skin configuration object. Specify order to
// ensure consistent import/export.
$skin = db_query("SELECT sid, uuid, theme, module, element, skin, options, status FROM {skinr_skins} WHERE sid = :sid", array(
':sid' => $sid,
))
->fetchObject();
// Unserialize options array.
$skin->options = unserialize($skin->options);
// Let modules modify the skin configuration.
module_invoke_all('skinr_skin_load', $skin);
return $skin;
}
/**
* Returns all default skin configuration objects.
*/
function _skinr_skin_get_defaults() {
$default_skins =& drupal_static(__FUNCTION__);
if (!isset($default_skins)) {
if ($cached = cache_get('skinr_skin_defaults')) {
$default_skins = $cached->data;
return $default_skins;
}
// Don't use module_invoke_all() to prevent oddly merged defaults.
$default_skins = array();
foreach (module_implements('skinr_skin_defaults') as $module) {
$function = $module . '_skinr_skin_defaults';
if (function_exists($function)) {
$result = call_user_func_array($function, array());
if (isset($result) && is_array($result)) {
$default_skins = array_merge($default_skins, $result);
}
elseif (isset($result)) {
$default_skins[] = $result;
}
}
}
// Let modules modify the skin configuration.
drupal_alter('skinr_skin_defaults', $default_skins);
cache_set('skinr_skin_defaults', $default_skins);
}
return $default_skins;
}
/**
* Imports default skin confiuration objects from code into database.
*
* @param $module_name
* Limit importing of defaults to a single module.
* @param $force
* If FALSE (default) the default skin will only be imported if the skin
* configuration doesn't exist, or if storage is default in code. If TRUE, the
* skin configuration in code will always be overwritten.
*
* @return
* If an import failed, returns FALSE. If all imports succeeded, returns TRUE.
*/
function skinr_skin_defaults_import($module_name = NULL, $force = FALSE) {
if (isset($module_name)) {
if (!($default_skins = module_invoke($module_name, 'skinr_skin_defaults'))) {
$default_skins = array();
}
drupal_alter('skinr_skin_defaults', $default_skins);
}
else {
$default_skins = _skinr_skin_get_defaults();
}
$status = TRUE;
foreach ($default_skins as $skin) {
$status = skinr_skin_import($skin, $force) && $status;
}
return $status;
}
/**
* Revert a skin configuration object that's stored in code to its default state.
*
* @param $sid
* A skin configuration ID.
*
* @return
* If revert failed, returns FALSE. If it succeeded, returns TRUE.
*/
function skinr_skin_revert($sid) {
if (!($uuid = skinr_skin_sid_to_uuid($sid))) {
return FALSE;
}
$default_skins = _skinr_skin_get_defaults();
if (!isset($default_skins[$uuid])) {
return FALSE;
}
if ($status = skinr_skin_import($default_skins[$uuid], TRUE)) {
drupal_static_reset('skinr_skin_uuid_to_sid');
drupal_static_reset('skinr_skin_sid_to_uuid');
}
return $status;
}
/**
* Import a skin configuration object as defined in skinr_skin_defaults().
*
* @param $default_skin
* A skin configuration object.
* @param $force
* If FALSE (default) the default skin will only be imported if the skin
* configuration doesn't exist, or if storage is default in code. If TRUE, the
* skin configuration in code will always be overwritten.
*
* @return
* If import failed, returns FALSE. If it succeeded, returns TRUE.
*/
function skinr_skin_import($default_skin, $force = FALSE) {
// Make sure we don't modify the cached default skin array.
$skin = clone $default_skin;
// Functionality is abstracted for use in skinr_skin_storage().
_skinr_skin_import($skin);
if (!$force && !empty($skin->sid)) {
// Load existing skin configuration from DB.
$db_skin = skinr_skin_load_unchanged($skin->sid);
// Sync status.
$skin->status = $db_skin->status;
if ($skin != $db_skin) {
// Skin exists and is overridden, so cancel import.
watchdog('skinr', 'Canceled import of skin with UUID %uuid and SID %sid. It is overridden.', array(
'%uuid' => $skin->uuid,
'%sid' => $skin->sid,
), WATCHDOG_WARNING);
return FALSE;
}
}
if ($status = skinr_skin_save($skin)) {
drupal_static_reset('skinr_skin_uuid_to_sid');
drupal_static_reset('skinr_skin_sid_to_uuid');
watchdog('skinr', 'Imported skin with UUID %uuid and SID %sid.', array(
'%uuid' => $skin->uuid,
'%sid' => $skin->sid,
), WATCHDOG_NOTICE);
}
else {
watchdog('skinr', 'Failed to import skin with UUID %uuid and SID %sid.', array(
'%uuid' => $skin->uuid,
'%sid' => isset($skin->sid) ? $skin->sid : t('unknown'),
), WATCHDOG_WARNING);
}
return $status;
}
function _skinr_skin_import(&$skin) {
if ($sid = skinr_skin_uuid_to_sid($skin->uuid)) {
$skin->sid = $sid;
}
// Let modules modify the skin configuration.
drupal_alter('skinr_skin_import', $skin);
}
/**
* Export var function.
*
* @see features_var_export()
*/
function skinr_var_export($var, $prefix = '', $init = TRUE) {
if (is_object($var)) {
$output = method_exists($var, 'export') ? $var
->export() : skinr_var_export((array) $var, '', FALSE);
}
else {
if (is_array($var)) {
if (empty($var)) {
$output = 'array()';
}
else {
$output = "array(\n";
foreach ($var as $key => $value) {
// Using normal var_export on the key to ensure correct quoting.
$output .= " " . var_export($key, TRUE) . " => " . skinr_var_export($value, ' ', FALSE) . ",\n";
}
$output .= ')';
}
}
else {
if (is_bool($var)) {
$output = $var ? 'TRUE' : 'FALSE';
}
else {
if (is_int($var)) {
$output = intval($var);
}
else {
if (is_numeric($var)) {
$output = floatval($var);
}
else {
if (is_string($var) && strpos($var, "\n") !== FALSE) {
// Replace line breaks in strings with a token for replacement
// at the very end. This protects whitespace in strings from
// unintentional indentation.
$var = str_replace("\n", "***BREAK***", $var);
$output = var_export($var, TRUE);
}
else {
$output = var_export($var, TRUE);
}
}
}
}
}
}
if ($prefix) {
$output = str_replace("\n", "\n{$prefix}", $output);
}
if ($init) {
$output = str_replace("***BREAK***", "\n", $output);
}
return $output;
}
/**
* Export object function.
*
* @see ctools_object_export()
*/
function skinr_object_export($object, $identifier, $prefix = '') {
$output = $prefix . '$' . $identifier . ' = new ' . get_class($object) . "();\n";
$output .= $prefix . '$' . $identifier . '->status = ';
if ($object->status) {
$output .= 'TRUE; /* Edit this to false to make a default ' . $identifier . ' disabled initially */' . "\n";
}
else {
$output .= 'FALSE; /* Edit this to true to make a default ' . $identifier . ' enabled initially */' . "\n";
}
$output .= $prefix . '$' . $identifier . '->api_version = ' . SKINR_VERSION . ";\n";
foreach ($object as $field => $value) {
if ($field == 'status') {
continue;
}
$output .= $prefix . '$' . $identifier . '->' . $field . ' = ' . skinr_var_export($value, $prefix) . ";\n";
}
return $output;
}
/**
* Output a skin configuration object as code suitable for skinr_skin_defaults().
*
* @param $skin
* A skin configuration object.
* @param $prefix
* A string to prefix the code with, used to indent the resulting code.
*
* @return
* A string.
*/
function skinr_skin_export($skin, $prefix = '') {
// Make sure we don't modify the cached skin object.
$skin = clone $skin;
// Let modules modify the skin configuration.
drupal_alter('skinr_skin_export', $skin, $prefix);
// Remove site specific $sid.
unset($skin->sid);
$output = skinr_object_export($skin, 'skin', $prefix);
$output .= $prefix . "\$skins['{$skin->uuid}'] = \$skin;\n";
return $output;
}
/**
* Returns a skin configuration object's storage method.
*
* @param $skin
* A skin configuration object.
*
* @return
* SKINR_STORAGE_IN_DATABASE if stored in the database,
* SKINR_STORAGE_IN_CODE if stored in code,
* SKINR_STORAGE_IN_CODE_OVERRIDDEN if stored in code and overridden in db.
*/
function skinr_skin_storage($skin) {
$default_skins = _skinr_skin_get_defaults();
$storage = SKINR_STORAGE_IN_DATABASE;
if (isset($default_skins[$skin->uuid])) {
$default_skin = clone $default_skins[$skin->uuid];
// Make sure skin has same processing as import.
_skinr_skin_import($default_skin);
// API version is only used for export.
unset($default_skin->api_version);
// Status shouldn't influence overridden.
$default_skin->status = $skin->status;
$storage = SKINR_STORAGE_IN_CODE;
if ($default_skin != $skin) {
// Default was overridden.
$storage = SKINR_STORAGE_IN_CODE_OVERRIDDEN;
}
}
return $storage;
}
/**
* Get skin configuration IDs.
*
* @param $filter_by
* An associative array whose keys are:
* - theme: (optional) The theme.
* - module: (optional) The module.
* - element: (optional) The element ID.
* - skin: (optional) The skin name.
* - status: (optional) Boolean indicating whether or not this skin
* configuration is enabled.
*
* @return
* An array of skin configuration IDs.
*/
function skinr_skin_get_sids($filter_by = array()) {
$query = db_select('skinr_skins', 's')
->fields('s', array(
'sid',
));
if (isset($filter_by['theme'])) {
$query
->condition('theme', $filter_by['theme']);
}
if (isset($filter_by['module'])) {
$query
->condition('module', $filter_by['module']);
}
if (isset($filter_by['element'])) {
$query
->condition('element', $filter_by['element']);
}
if (isset($filter_by['skin'])) {
$query
->condition('skin', $filter_by['skin']);
}
if (isset($filter_by['status'])) {
$query
->condition('status', $filter_by['status']);
}
return $query
->execute()
->fetchCol();
}
/**
* 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.
*
* @param $exclude_admin_theme
* Optional. Set to TRUE to exclude the admin theme from possible themes to
* return.
*
* @return
* The current theme name.
*
* @see drupal_theme_initialize()
*/
function skinr_current_theme($exclude_admin_theme = FALSE) {
global $user, $theme;
// Drupal core, and modules such as themkey and og_theme, set the theme
// through hook_custom_theme() or hook_menu() using 'theme callback', which
// are all picked up by menu_get_custom_theme().
$current_theme = $theme;
if ($exclude_admin_theme) {
// Only select the user selected theme if it is available in the
// list of themes that can be accessed.
$current_theme = !empty($user->theme) && drupal_theme_access($user->theme) ? $user->theme : variable_get('theme_default', 'bartik');
// Allow modules to override the theme. Validation has already been performed
// inside menu_get_custom_theme(), so we do not need to check it again here.
$custom_theme = menu_get_custom_theme();
if ($custom_theme != variable_get('admin_theme', '0')) {
$current_theme = !empty($custom_theme) ? $custom_theme : $current_theme;
}
}
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;
}
/**
* Retrieve the overridden status of a skin.
*
* @param $skin_info
* Information about a registered skin.
*
* @return
* An array of statuses for each enabled theme. If no overrides are found,
* the status defaults will be returned.
*/
function skinr_skin_info_status_get($skin_info) {
return variable_get('skinr_skin_' . $skin_info['name'] . '_status', $skin_info['status']);
}
/**
* Set the status of a skin. Overrides the skin plugin settings.
*
* @param $skin_info
* Information about a registered skin.
* @param $status
* An array of statuses for each theme.
*/
function skinr_skin_info_status_set($skin_info, $status) {
variable_set('skinr_skin_' . $skin_info['name'] . '_status', $status);
}
/**
* Helper function to determine whether or not a given file is local or not.
*/
function _skinr_is_local_file($file) {
if (strpos($file, 'http://') === 0 || strpos($file, 'https://') === 0 || strpos($file, '/') === 0) {
return FALSE;
}
if (!file_exists($file)) {
return FALSE;
}
return TRUE;
}
function _skinr_preprocess_attached(&$attached, $source) {
foreach (array(
'css',
'js',
) as $type) {
if (isset($attached[$type])) {
$keys = array_keys($attached[$type]);
foreach ($keys as $pos => $key) {
$options = $attached[$type][$key];
// If the value is not an array, it's a filename and passed as first
// (and only) argument. Turn it into an array so we can insert our defaults.
if (!is_array($options)) {
$key = $options;
$options = array();
$attached[$type][$key] = $options;
_skinr_array_splice($attached[$type], $pos, 1, array(
$key => $options,
));
}
// Add path to relative stylesheet and script paths. If the url is
// absolute (e.g. the url start with 'http://' or 'https://') or
// relative to the site's root (e.g. the url starts with '/') the path
// does not get prepended.
if (is_numeric($key)) {
// If $options is an array, but $key is not a filename, find $key in
// the $options array.
if (_skinr_is_local_file($source['path'] . '/' . $options['data'])) {
$attached[$type][$key]['data'] = $source['path'] . '/' . $options['data'];
}
}
elseif (_skinr_is_local_file($source['path'] . '/' . $key)) {
$key = $source['path'] . '/' . $key;
_skinr_array_splice($attached[$type], $pos, 1, array(
$key => $options,
));
}
// Add in defaults.
$attached[$type][$key] += array(
'preprocess' => FALSE,
);
}
}
}
}
/**
* Helper function to remove a portion of an array and replace it with something else.
*/
function _skinr_array_splice(array &$array, $offset, $length = 0, array $replacement = NULL) {
if (is_null($replacement)) {
$replacement = array();
}
$array = array_slice($array, 0, $offset, true) + $replacement + array_slice($array, $offset + $length, NULL, true);
}
/**
* 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
* An array of skins as returned from skin plugins.
* @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]);
_skinr_preprocess_attached($skin_infos[$skin_name]['attached'], $source);
foreach ($skin_infos[$skin_name]['options'] as $option_name => $option) {
if (isset($option['attached'])) {
_skinr_preprocess_attached($skin_infos[$skin_name]['options'][$option_name]['attached'], $source);
}
// Validate class by running it through drupal_html_class().
if (!is_array($skin_infos[$skin_name]['options'][$option_name]['class'])) {
// Raise an error.
watchdog('skinr', 'The class for option %option in skin %skin needs to be an array.', array(
'%option' => $option_name,
'%skin' => $skin_name,
), WATCHDOG_WARNING);
// Reset to array to prevent errors.
$skin_infos[$skin_name]['options'][$option_name]['class'] = array();
}
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_api() as $name => $extension) {
$hooks = array();
// Run through skinr_hook to ensure the required include gets loaded.
if (skinr_hook($name, 'skinr_skin_info')) {
$hooks["{$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) {
$path = $dir . '/' . basename(dirname($file->uri));
$hooks["{$name}_skinr_skin_{$plugin}_info"] = array(
// The source path for a plugin is the plugin directory.
'path' => $path,
'include file' => $path . '/' . $file->filename,
) + $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_api() as $name => $extension) {
$hooks = array();
// Run through skinr_hook to ensure the required include gets loaded.
if (skinr_hook($name, 'skinr_group_info')) {
$hooks["{$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) {
$path = $dir . '/' . basename(dirname($file->uri));
$hooks["{$name}_skinr_group_{$plugin}_info"] = array(
// The source path for a plugin is the plugin directory.
'path' => $path,
'include file' => $path . '/' . $file->filename,
) + $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_info)) {
if ($cached = cache_get('skinr_config_info')) {
$config_info = $cached->data;
return $config_info;
}
$config_info = skinr_invoke_all('skinr_config_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;
}
/**
* Provide a list of all available theme hooks for a given element.
*
* @param $module
* The module implementing given element.
* @param $element
* An element.
*
* @return
* An array of theme hooks.
*/
function skinr_theme_hooks($module, $element) {
$theme_hooks =& drupal_static(__FUNCTION__, array());
if (!isset($theme_hooks[$module][$element])) {
// Invoke hook_skinr_theme_hooks() and hook_skinr_theme_hooks_alter().
$theme_hooks[$module][$element] = skinr_invoke_all('skinr_theme_hooks', $module, $element);
drupal_alter('skinr_theme_hooks', $theme_hooks[$module][$element], $module, $element);
}
return $theme_hooks[$module][$element];
}
/**
* Implements hook_modules_enabled().
*/
function skinr_modules_enabled($modules) {
skinr_cache_reset();
foreach ($modules as $module) {
skinr_skin_defaults_import($module);
}
}
/**
* 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();
}
/**
* Helper function for built-in integration code.
*/
function skinr_skinr_api_modules() {
return array(
'path' => drupal_get_path('module', 'skinr') . '/modules',
);
}
function block_skinr_api_2() {
return skinr_skinr_api_modules();
}
function comment_skinr_api_2() {
return skinr_skinr_api_modules();
}
function node_skinr_api_2() {
return skinr_skinr_api_modules();
}
function system_skinr_api_2() {
return skinr_skinr_api_modules();
}
function views_skinr_api_2() {
return skinr_skinr_api_modules();
}
Functions
Name | Description |
---|---|
block_skinr_api_2 | |
comment_skinr_api_2 | |
node_skinr_api_2 | |
skinr_cache_reset | Clears cached Skinr information. |
skinr_current_theme | Helper function to retrieve the current theme. |
skinr_exit | Implements hook_exit(). |
skinr_flatten_skins_array | Returns an array of classes. |
skinr_get_config_info | Fetch Skinr configuration data from functionality plugins. |
skinr_get_group_info | Retrieves all skin groups registered by modules and themes. |
skinr_get_skin_info | Retrieves all skins registered by modules and themes. |
skinr_help | Implements hook_help(). |
skinr_hook | Determine whether a module implements a hook. |
skinr_hook_info | Implements hook_hook_info(). |
skinr_implements | Determine which modules are implementing a hook. |
skinr_implements_api | Returns a list of extensions that implement this API version of Skinr. |
skinr_include_once | file_scan_directory() callback wrapper around include_once. |
skinr_invoke_all | Invoke a hook in all enabled modules and themes that implement it. |
skinr_load_include | Loads a $module.skinr.inc include file. |
skinr_load_plugins | Includes Skinr plugin files for an extension, if any. |
skinr_modules_disabled | Implements hook_modules_disabled(). |
skinr_modules_enabled | Implements hook_modules_enabled(). |
skinr_object_export | Export object function. |
skinr_preprocess | Implements hook_preprocess(). |
skinr_skinr_api_modules | Helper function for built-in integration code. |
skinr_skin_defaults_import | Imports default skin confiuration objects from code into database. |
skinr_skin_delete | Delete a skin object. |
skinr_skin_delete_multiple | Delete multiple skin configuration objects. |
skinr_skin_export | Output a skin configuration object as code suitable for skinr_skin_defaults(). |
skinr_skin_get_sids | Get skin configuration IDs. |
skinr_skin_import | Import a skin configuration object as defined in skinr_skin_defaults(). |
skinr_skin_info_process | Parse a skin_infos array as returned from a skins plugin. |
skinr_skin_info_status_default | Prepare the default status for a skin. |
skinr_skin_info_status_get | Retrieve the overridden status of a skin. |
skinr_skin_info_status_set | Set the status of a skin. Overrides the skin plugin settings. |
skinr_skin_load | Load a skin configuration object from the database. |
skinr_skin_load_by_uuid | Load a skin configuration object from the database using UUID. |
skinr_skin_load_multiple | Load skin configuration objects from the database. |
skinr_skin_load_unchanged | Load an uncached version of a skin configuration object. |
skinr_skin_revert | Revert a skin configuration object that's stored in code to its default state. |
skinr_skin_save | Save a skin object. |
skinr_skin_sid_to_uuid | Get skin configuration IDs. |
skinr_skin_storage | Returns a skin configuration object's storage method. |
skinr_skin_uuid_to_sid | Get skin configuration IDs. |
skinr_skin_validate | Validate a skinr object. |
skinr_themes_disabled | Implements hook_themes_disabled(). |
skinr_themes_enabled | Implements hook_themes_enabled(). |
skinr_theme_hooks | Provide a list of all available theme hooks for a given element. |
skinr_var_export | Export var function. |
system_skinr_api_2 | |
views_skinr_api_2 | |
_skinr_array_splice | Helper function to remove a portion of an array and replace it with something else. |
_skinr_array_strip_empty | Helper function to remove empty skins from an array. |
_skinr_is_local_file | Helper function to determine whether or not a given file is local or not. |
_skinr_preprocess_attached | |
_skinr_skin_get_defaults | Returns all default skin configuration objects. |
_skinr_skin_import |
Constants
Name | Description |
---|---|
SKINR_STORAGE_IN_CODE | |
SKINR_STORAGE_IN_CODE_OVERRIDDEN | |
SKINR_STORAGE_IN_DATABASE | A flag used to let us know if an object is in the database. |
SKINR_VERSION | The Skinr API version. |