summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/color/color.module160
-rw-r--r--modules/system/system.install14
-rw-r--r--themes/garland/color/color.inc17
-rw-r--r--themes/garland/minnelli/color/color.inc17
4 files changed, 148 insertions, 60 deletions
diff --git a/modules/color/color.module b/modules/color/color.module
index b19043acb..980c046f1 100644
--- a/modules/color/color.module
+++ b/modules/color/color.module
@@ -2,20 +2,20 @@
// $Id$
/**
- * Implementation of hook_help
+ * Implementation of hook_help().
*/
function color_help($path, $arg) {
switch ($path) {
case 'admin/help#color':
$output = '<p>'. t('The color module allows a site administrator to quickly and easily change the color scheme of certain themes. Although all themes do not support color module, both Garland, the default theme, and Minnelli, its fixed width counterpart, were designed to take advantage of its features. By using color module with a compatible theme, you can easily change the color of links, backgrounds, text, and other theme elements. Color module requires that your <a href="@url">file download method</a> be set to public.', array('@url' => url('admin/settings/file-system'))) .'</p>';
- $output .= '<p>'. t("It is important to remember that color module saves a modified copy of the theme's style.css file in the files directory, and includes it after the theme's original style.css. This means that if you make any manual changes to your theme's style.css file, you must save your color settings again, even if they haven't changed. This causes the color module generated version of style.css in the files directory to be recreated using the new version of the original file.") .'</p>';
+ $output .= '<p>'. t("It is important to remember that color module saves a modified copy of the theme's specified stylesheets in the files directory. This means that if you make any manual changes to your theme's stylesheet, you must save your color settings again, even if they haven't changed. This causes the color module generated version of the stylesheets in the files directory to be recreated using the new version of the original file.") .'</p>';
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@color">Color page</a>.', array('@color' => 'http://drupal.org/handbook/modules/color/')) .'</p>';
return $output;
}
}
/**
- * Implementation of hook_theme()
+ * Implementation of hook_theme().
*/
function color_theme() {
return array(
@@ -24,12 +24,13 @@ function color_theme() {
),
);
}
+
/**
* Implementation of hook_form_alter().
*/
function color_form_alter(&$form, $form_state, $form_id) {
// Insert the color changer into the theme settings page.
- // TODO: Last condition in the following if disables color changer when private files are used this should be solved in a different way. See issue #92059.
+ // TODO: Last condition in the following if disables color changer when private files are used. This should be solved in a different way. See issue #92059.
if ($form_id == 'system_theme_settings' && color_get_info(arg(4)) && function_exists('gd_info') && variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC) {
$form['color'] = array(
'#type' => 'fieldset',
@@ -42,7 +43,7 @@ function color_form_alter(&$form, $form_state, $form_id) {
$form['#submit'][] = 'color_scheme_form_submit';
}
- // Use the generated screenshot in the theme list
+ // Use the generated screenshot in the theme list.
if ($form_id == 'system_theme_select_form' || $form_id == 'system_themes') {
$themes = list_themes();
foreach (element_children($form) as $theme) {
@@ -59,16 +60,49 @@ function color_form_alter(&$form, $form_state, $form_id) {
* Callback for the theme to alter the resources used.
*/
function _color_page_alter(&$vars) {
- global $theme_key;
-
- // Override stylesheet
- $path = variable_get('color_'. $theme_key .'_stylesheet', NULL);
- if ($path) {
- $vars['css']['all']['theme'][$path] = TRUE;
+ global $language, $theme_key;
+
+ // Override stylesheets.
+ $color_paths = variable_get('color_'. $theme_key .'_stylesheets', array());
+ if (!empty($color_paths)) {
+ // Loop over theme CSS files and try to rebuild CSS array with rewritten
+ // stylesheets. Keep the orginal order intact for CSS cascading.
+ $new_theme_css = array();
+
+ foreach ($vars['css']['all']['theme'] as $old_path => $old_preprocess) {
+ // Add the non-colored stylesheet first as we might not find a
+ // re-colored stylesheet for replacement later.
+ $new_theme_css[$old_path] = $old_preprocess;
+
+ // Loop over the path array with recolored CSS files to find matching
+ // paths which could replace the non-recolored paths.
+ foreach ($color_paths as $color_path) {
+ // Color module currently requires unique file names to be used,
+ // which allows us to compare different file paths.
+ if (basename($old_path) == basename($color_path)) {
+ // Pull out the non-colored and add rewritten stylesheet.
+ unset($new_theme_css[$old_path]);
+ $new_theme_css[$color_path] = $old_preprocess;
+
+ // If the current language is RTL and the CSS file had an RTL variant,
+ // pull out the non-colored and add rewritten RTL stylesheet.
+ if (defined('LANGUAGE_RTL') && $language->direction == LANGUAGE_RTL) {
+ $rtl_old_path = str_replace('.css', '-rtl.css', $old_path);
+ $rtl_color_path = str_replace('.css', '-rtl.css', $color_path);
+ if (file_exists($rtl_color_path)) {
+ unset($new_theme_css[$rtl_old_path]);
+ $new_theme_css[$rtl_color_path] = $old_preprocess;
+ }
+ }
+ break;
+ }
+ }
+ }
+ $vars['css']['all']['theme'] = $new_theme_css;
$vars['styles'] = drupal_get_css($vars['css']);
}
- // Override logo
+ // Override logo.
$logo = variable_get('color_'. $theme_key .'_logo', NULL);
if ($logo && $vars['logo'] && preg_match('!'. $theme_key .'/logo.png$!', $vars['logo'])) {
$vars['logo'] = base_path() . $logo;
@@ -244,14 +278,14 @@ function color_scheme_form_submit($form, &$form_state) {
if (implode(',', color_get_palette($theme, true)) == implode(',', $palette)
|| $form_state['values']['op'] == t('Reset to defaults')) {
variable_del('color_'. $theme .'_palette');
- variable_del('color_'. $theme .'_stylesheet');
+ variable_del('color_'. $theme .'_stylesheets');
variable_del('color_'. $theme .'_logo');
variable_del('color_'. $theme .'_files');
variable_del('color_'. $theme .'_screenshot');
return;
}
- // Prepare target locations for generated files
+ // Prepare target locations for generated files.
$id = $theme .'-'. substr(md5(serialize($palette) . microtime()), 0, 8);
$paths['color'] = file_directory_path() .'/color';
$paths['target'] = $paths['color'] .'/'. $id;
@@ -261,15 +295,13 @@ function color_scheme_form_submit($form, &$form_state) {
$paths['target'] = $paths['target'] .'/';
$paths['id'] = $id;
$paths['source'] = drupal_get_path('theme', $theme) .'/';
- $paths['stylesheet'] = $paths['target'] .'style.css';
$paths['files'] = $paths['map'] = array();
- // Save palette and stylesheet location
+ // Save palette and logo location.
variable_set('color_'. $theme .'_palette', $palette);
- variable_set('color_'. $theme .'_stylesheet', $paths['stylesheet']);
variable_set('color_'. $theme .'_logo', $paths['target'] .'logo.png');
- // Copy over neutral images
+ // Copy over neutral images.
foreach ($info['copy'] as $file) {
$base = basename($file);
$source = $paths['source'] . $file;
@@ -278,23 +310,55 @@ function color_scheme_form_submit($form, &$form_state) {
$paths['files'][] = $paths['target'] . $base;
}
- // Render new images
+ // Render new images.
_color_render_images($theme, $info, $paths, $palette);
- // Rewrite stylesheet
- _color_rewrite_stylesheet($theme, $info, $paths, $palette);
+ // Rewrite theme stylesheets.
+ $css = array();
+ foreach ($info['css'] as $stylesheet) {
+ // Build a temporary array with LTR and RTL files.
+ $files = array();
+ if (file_exists($paths['source'] . $stylesheet)) {
+ $files[] = $stylesheet;
+
+ $rtl_file = str_replace('.css', '-rtl.css', $stylesheet);
+ if (file_exists($paths['source'] . $rtl_file)) {
+ $files[] = $rtl_file;
+ }
+ }
+
+ foreach ($files as $file) {
+ // Aggregate @imports recursively for each configured top level CSS file
+ // without optimization. Aggregation and optimization will be
+ // handled by drupal_build_css_cache() only.
+ $style = drupal_load_stylesheet($paths['source'] . $file, FALSE);
+
+ // Return the path to where this CSS file originated from, stripping
+ // off the name of the file at the end of the path.
+ $base = base_path() . dirname($paths['source'] . $file) .'/';
+ _drupal_build_css_path(NULL, $base);
+
+ // Prefix all paths within this CSS file, ignoring absolute paths.
+ $style = preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $style);
- // Maintain list of files
+ // Rewrite stylesheet with new colors.
+ $style = _color_rewrite_stylesheet($theme, $info, $paths, $palette, $style);
+ $base_file = basename($file);
+ $css[] = $paths['target'] . $base_file;
+ _color_save_stylesheet($paths['target'] . $base_file, $style, $paths);
+ }
+ }
+
+ // Maintain list of files.
+ variable_set('color_'. $theme .'_stylesheets', $css);
variable_set('color_'. $theme .'_files', $paths['files']);
}
/**
* Rewrite the stylesheet to match the colors in the palette.
*/
-function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette) {
- // Load stylesheet
+function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette, $style) {
$themes = list_themes();
- $style = file_get_contents($themes[$theme]->stylesheets['all']['style.css']);
// Prepare color conversion table
$conversion = $palette;
@@ -305,13 +369,10 @@ function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette) {
$default = color_get_palette($theme, true);
// Split off the "Don't touch" section of the stylesheet.
- list($style, $fixed) = explode("Color Module: Don't touch", $style);
-
- // Look for @import commands and insert the referenced stylesheets.
- $cwd = getcwd();
- chdir(drupal_get_path('theme', $theme));
- $style = preg_replace_callback('/@import\s*["\']([^"\']+)["\'];/', '_color_import_stylesheet', $style);
- chdir($cwd);
+ $split = "Color Module: Don't touch";
+ if (strpos($split, $style) !== FALSE) {
+ list($style, $fixed) = explode($split, $style);
+ }
// Find all colors in the stylesheet and the chunks in between.
$style = preg_split('/(#[0-9a-f]{6}|#[0-9a-f]{3})/i', $style, -1, PREG_SPLIT_DELIM_CAPTURE);
@@ -319,11 +380,11 @@ function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette) {
$output = '';
$base = 'base';
- // Iterate over all parts
+ // Iterate over all parts.
foreach ($style as $chunk) {
if ($is_color) {
$chunk = drupal_strtolower($chunk);
- // Check if this is one of the colors in the default palette
+ // Check if this is one of the colors in the default palette.
if ($key = array_search($chunk, $default)) {
$chunk = $conversion[$key];
}
@@ -351,29 +412,32 @@ function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette) {
$output .= $chunk;
$is_color = !$is_color;
}
- // Append fixed colors segment
- $output .= $fixed;
+ // Append fixed colors segment.
+ if (isset($fixed)) {
+ $output .= $fixed;
+ }
- // Replace paths to images
+ // Replace paths to images.
foreach ($paths['map'] as $before => $after) {
+ $before = base_path() . $paths['source'] . $before;
+ $before = preg_replace('`(^|/)(?!../)([^/]+)/../`', '$1', $before);
$output = str_replace($before, $after, $output);
}
- // Write new stylesheet
- $file = fopen($paths['stylesheet'], 'w+');
- fwrite($file, $output);
- fclose($file);
- $paths['files'][] = $paths['stylesheet'];
-
- // Set standard file permissions for webserver-generated files
- @chmod($paths['stylesheet'], 0664);
+ return $output;
}
/**
- * Helper function for _color_rewrite_stylesheet.
+ * Save the rewritten stylesheet to disk.
*/
-function _color_import_stylesheet($matches) {
- return preg_replace('/url\(([\'"]?)(?![a-z]+:)/i', 'url(\1'. dirname($matches[1]) .'/', file_get_contents($matches[1]));
+function _color_save_stylesheet($file, $style, &$paths) {
+
+ // Write new stylesheet.
+ file_save_data($style, $file, FILE_EXISTS_REPLACE);
+ $paths['files'][] = $file;
+
+ // Set standard file permissions for webserver-generated files.
+ @chmod($file, 0664);
}
/**
diff --git a/modules/system/system.install b/modules/system/system.install
index c25268c61..218ab61d0 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -2728,6 +2728,20 @@ function system_update_6041() {
}
/**
+ * Upgrade recolored theme stylesheets to new array structure.
+ */
+function system_update_6042() {
+ foreach (list_themes() as $theme) {
+ $stylesheet = variable_get('color_'. $theme->name .'_stylesheet', NULL);
+ if (!empty($stylesheet)) {
+ variable_set('color_'. $theme->name .'_stylesheets', array($stylesheet));
+ variable_del('color_'. $theme->name .'_stylesheet');
+ }
+ }
+ return array();
+}
+
+/**
* @} End of "defgroup updates-5.x-to-6.x"
* The next series of updates should start at 7000.
*/
diff --git a/themes/garland/color/color.inc b/themes/garland/color/color.inc
index d5a3d4d47..10d76dedd 100644
--- a/themes/garland/color/color.inc
+++ b/themes/garland/color/color.inc
@@ -3,7 +3,7 @@
$info = array(
- // Pre-defined color schemes
+ // Pre-defined color schemes.
'schemes' => array(
'#0072b9,#027ac6,#2385c2,#5ab5ee,#494949' => t('Blue Lagoon (Default)'),
'#464849,#2f416f,#2a2b2d,#5d6779,#494949' => t('Ash'),
@@ -22,7 +22,7 @@ $info = array(
'#18583d,#1b5f42,#34775a,#52bf90,#2d2d2d' => t('Teal Top'),
),
- // Images to copy over
+ // Images to copy over.
'copy' => array(
'images/menu-collapsed.gif',
'images/menu-collapsed-rtl.gif',
@@ -30,10 +30,15 @@ $info = array(
'images/menu-leaf.gif',
),
- // Coordinates of gradient (x, y, width, height)
+ // CSS files (excluding @import) to rewrite with new color scheme.
+ 'css' => array(
+ 'style.css',
+ ),
+
+ // Coordinates of gradient (x, y, width, height).
'gradient' => array(0, 37, 760, 121),
- // Color areas to fill (x, y, width, height)
+ // Color areas to fill (x, y, width, height).
'fill' => array(
'base' => array(0, 0, 760, 568),
'link' => array(107, 533, 41, 23),
@@ -61,10 +66,10 @@ $info = array(
// Reference color used for blending. Matches the base.png's colors.
'blend_target' => '#ffffff',
- // Preview files
+ // Preview files.
'preview_image' => 'color/preview.png',
'preview_css' => 'color/preview.css',
- // Base file for image generation
+ // Base file for image generation.
'base_image' => 'color/base.png',
);
diff --git a/themes/garland/minnelli/color/color.inc b/themes/garland/minnelli/color/color.inc
index c00fe92e6..eab1235be 100644
--- a/themes/garland/minnelli/color/color.inc
+++ b/themes/garland/minnelli/color/color.inc
@@ -3,7 +3,7 @@
$info = array(
- // Pre-defined color schemes
+ // Pre-defined color schemes.
'schemes' => array(
'#0072b9,#027ac6,#2385c2,#5ab5ee,#494949' => t('Blue Lagoon (Default)'),
'#464849,#2f416f,#2a2b2d,#5d6779,#494949' => t('Ash'),
@@ -22,7 +22,7 @@ $info = array(
'#18583d,#1b5f42,#34775a,#52bf90,#2d2d2d' => t('Teal Top'),
),
- // Images to copy over
+ // Images to copy over.
'copy' => array(
'../images/menu-collapsed.gif',
'../images/menu-collapsed-rtl.gif',
@@ -30,10 +30,15 @@ $info = array(
'../images/menu-leaf.gif',
),
- // Coordinates of gradient (x, y, width, height)
+ // CSS files (excluding @import) to rewrite with new color scheme.
+ 'css' => array(
+ '../style.css',
+ ),
+
+ // Coordinates of gradient (x, y, width, height).
'gradient' => array(0, 37, 760, 121),
- // Color areas to fill (x, y, width, height)
+ // Color areas to fill (x, y, width, height).
'fill' => array(
'base' => array(0, 0, 760, 568),
'link' => array(107, 533, 41, 23),
@@ -61,10 +66,10 @@ $info = array(
// Reference color used for blending. Matches the base.png's colors.
'blend_target' => '#ffffff',
- // Preview files
+ // Preview files.
'preview_image' => 'color/preview.png',
'preview_css' => '../color/preview.css',
- // Base file for image generation
+ // Base file for image generation.
'base_image' => 'color/base.png',
);