magic.assets.inc in Magic 7.2
A file to contain functions for the magic module to abuse.
File
includes/magic.assets.incView source
<?php
/**
* @file
* A file to contain functions for the magic module to abuse.
*/
/**
* Helper function for generating a regex from a list of paths.
*
* Generates a single regex from a list of file paths that can be used to match
* JS or CSS files using preg_grep() for example in hook_css_alter() or
* hook_js_alter(). The '*' (asterisk) character can be used as a wild-card.
*
* @param $paths
* An array of file paths.
*
* @return string
* The generated regex.
*
* @see hook_js_alter()
* @see hook_css_alter()
*/
function magic_assets_prepare_regex($paths) {
$profile = drupal_get_profile();
$site = preg_quote(conf_path(), '/');
$themes = array();
foreach ($GLOBALS['base_theme_info'] as $info) {
$themes[] = preg_quote(dirname($info->filename), '/');
}
$tokens = array(
':all' => '.+',
':core' => '(?:misc|modules|themes)\\/.+',
':contrib' => "(?:sites\\/all\\/modules|{$site}\\/modules|profiles\\/{$profile}\\/modules)\\/.+",
':current-theme' => preg_quote(drupal_get_path('theme', $GLOBALS['theme_key']), '/') . "\\/.+",
':base-theme' => $themes ? '(?:' . implode('|', $themes) . ')\\/.+' : FALSE,
);
foreach ($paths as &$item) {
// The first segment (everything before the first slash) is the namespace.
// This rule only applies to local files... So if the namespace can not be
// mapped to a token, module, profile or theme engine we assume that we are
// trying to target an external file.
list($namespace) = explode('/', $item, 2);
// Process token namespaces.
if (isset($tokens[$namespace]) && empty($tokens[$namespace])) {
unset($item);
continue;
}
elseif ($namespace != '*' && !isset($tokens[$namespace])) {
// Check if it refers to a theme, module, profile or theme engine.
foreach (array(
'theme',
'module',
'profile',
'theme_engine',
) as $type) {
// We can't use drupal_get_path() directly because that uses dirname()
// internally which returns '.' if no filename was found.
if ($filename = drupal_get_filename($type, $namespace, NULL, FALSE)) {
$directory = preg_quote(dirname($filename), '/');
// Now that we know about this namespace we can add it to the tokens
// array for performance reasons.
$tokens[$namespace] = $directory;
break;
}
}
}
// Escape any regex characters and replace tokens and wildcards.
$item = isset($tokens[$namespace]) ? substr($item, strlen($namespace)) : $item;
$item = preg_quote($item, '/');
$item = str_replace('\\*', '.*', $item);
$item = isset($tokens[$namespace]) ? $tokens[$namespace] . $item : $item;
}
return empty($paths) ? FALSE : '/^' . implode('|', $paths) . '$/';
}
/**
* Groups include/exclude patterns together.
*
* This is required to allow for complex chained includes/excludes. We can't do
* this in a single, complicated regular expression as regex does not really
* support this (negative lookbehinds are not sufficient).
*
* @param $items
* An array of include/exclude patterns.
*
* @return array
* The include/exclude patterns as groups.
*/
function magic_assets_regex_steps($items) {
$switch = FALSE;
$key = 0;
$groups = array();
// Iterate over all exclude/include paths and form groups. We start a new
// group every time we switch from inclusion to exclusion.
foreach ($items as $item) {
// If an item starts with a "~" it is an inclusion pattern.
if ($exclude = strpos($item, '~') === 0) {
$item = substr($item, 1);
}
// Start a new group if we are switching between exclusion/inclusion.
if ($switch !== $exclude && ($switch = !$switch) === FALSE) {
$key++;
}
// Initialize the group with two empty arrays if it does not exist yet.
if (!isset($groups[$key])) {
$groups[$key] = array_fill(0, 2, array());
}
$groups[$key][!$switch ? 0 : 1][] = $item;
}
// Each group now needs to have its items converted to a regex string.
foreach ($groups as &$group) {
foreach (array(
0,
1,
) as $key) {
$group[$key] = !empty($group[$key]) ? magic_assets_prepare_regex($group[$key]) : FALSE;
}
}
return $groups;
}
/**
* Eliminates elements from an array using a simplified regex pattern.
*
* @param $elements
* The array of elements that should have some of its items removed.
* @param $steps
* A set of regex as generated by magic_prepare_regex().
*/
function magic_assets_exclude(&$elements, $steps) {
$mapping = magic_assets_generate_mapping($elements);
$remove = array();
foreach ($steps as $step) {
list($exclude, $include) = $step;
$remove += preg_grep($exclude, !empty($remove) ? array_diff_key($mapping, $remove) : $mapping);
if (!empty($include)) {
$remove = array_diff_key($remove, preg_grep($include, $remove));
}
}
$elements = array_diff_key($elements, $remove);
}
/**
* Helper function for generating a map of assets based on the data attribute.
*
* We can not rely on the array keys of the JS and CSS file arrays in Drupal
* because in case of inline JS or CSS (which uses numerical array keys) and due
* to potential overrides of the 'data' attribute which holds the actual,
* reliable path of the file. This function returns a single-level array of
* reliable JS/CSS file paths using the original array keys as keys. Elements of
* type 'inline' or 'setting' are ignored.
*
* @param $elements
* An array of JS or CSS files as given in hook_css_alter() or
* hook_js_alter().
*
* @return array
* A map of file paths generated from $elements.
*
* @see hook_js_alter()
* @see hook_css_alter()
*/
function magic_assets_generate_mapping($elements) {
$mapping = array();
foreach ($elements as $key => $item) {
if ($item['type'] == 'inline' || $item['type'] == 'setting') {
// Naturally, in-line CSS is not supported.
continue;
}
// We need to build an array containing just the 'data' attribute because
// that's the actual path of the file. The array key of the elements can
// be something else if someone is sneaky enough to use drupal_add_js() or
// drupal_add_css() with a bogus first argument (normally, that is the
// path to the file) and then specify the actual path through the 'data'
// attribute in the $options array.
$mapping[$key] = $item['data'];
}
return $mapping;
}
Functions
Name | Description |
---|---|
magic_assets_exclude | Eliminates elements from an array using a simplified regex pattern. |
magic_assets_generate_mapping | Helper function for generating a map of assets based on the data attribute. |
magic_assets_prepare_regex | Helper function for generating a regex from a list of paths. |
magic_assets_regex_steps | Groups include/exclude patterns together. |