File

includes/css.inc

View source
<?php

function advagg_process_html_css(&$variables) {
    // dpm($variables);
    return;
    $schema = advagg_get_server_schema();
    $css_var = $variables['css'];
    $css_orig = $css_var;
    if (!variable_get('advagg_only_css_from_variables', ADVAGG_ONLY_CSS_FROM_VARIABLES)) {
        $css_func = drupal_add_css(CSS_DEFAULT);
        advagg_css_array_fixer($css_func);
    }
    else {
        $css_func = array();
    }
    $css = array_merge($css_var, $css_func);
    $css_func_inline = advagg_add_css_inline();
    if (!empty($css_func_inline)) {
        $css = advagg_merge_inline_css($css, $css_func_inline);
    }
    $css_conditional_styles = !empty($variables['conditional_styles']) ? $variables['conditional_styles'] : '';
    $css_styles = $variables['styles'];
    // Try cache.
    if (variable_get('advagg_use_full_cache', ADVAGG_USE_FULL_CACHE)) {
        // Build the cache ID
        // md5 of the CSS input
        // http or https
        // hostname
        // the js rendering function
        // css/js query string
        $cid = 'advagg_processor:css:' . md5(serialize(array(
            $css,
            $css_conditional_styles,
        ))) . ':' . $schema . ':' . $_SERVER['HTTP_HOST'] . ':' . variable_get('advagg_css_render_function', ADVAGG_CSS_RENDER_FUNCTION) . ':' . substr(variable_get('css_js_query_string', '0'), 0, 1);
        $cache = cache_get($cid, 'cache_advagg_bundle_reuse');
    }
    elseif (isset($cid)) {
        unset($cid);
    }
    if (!empty($cache->data)) {
        $variables['styles'] = $cache->data;
    }
    else {
        // Build HTML code.
        $processed_css = advagg_process_css($css);
        if (!empty($processed_css)) {
            $variables['styles'] = $processed_css;
        }
        $variables['styles'] .= $css_conditional_styles;
        // Cache output.
        if (isset($cid) && variable_get('advagg_use_full_cache', ADVAGG_USE_FULL_CACHE) && lock_acquire($cid)) {
            cache_set($cid, $variables['styles'], 'cache_advagg_bundle_reuse', CACHE_TEMPORARY);
            lock_release($cid);
        }
    }
}

/**
 * Returns a themed representation of all stylesheets that should be attached to
 * the page.
 *
 * @see drupal_get_css()
 *
 * It loads the CSS in order, with 'module' first, then 'theme' afterwards.
 * This ensures proper cascading of styles so themes can easily override
 * module styles through CSS selectors.
 *
 * Themes may replace module-defined CSS files by adding a stylesheet with the
 * same filename. For example, themes/garland/system-menus.css would replace
 * modules/system/system-menus.css. This allows themes to override complete
 * CSS files, rather than specific selectors, when necessary.
 *
 * If the original CSS file is being overridden by a theme, the theme is
 * responsible for supplying an accompanying RTL CSS file to replace the
 * module's.
 *
 * @param $css
 *   (optional) An array of CSS files. If no array is provided, the default
 *   stylesheets array is used instead.
 * @param $noagg
 *   (optional) Bool indicating that aggregation should be disabled if TRUE.
 * @return
 *   A string of XHTML CSS tags.
 */
function advagg_process_css($css = NULL, $noagg = FALSE) {
    global $conf;
    $original_css = $css;
    if (!isset($css)) {
        $css = drupal_add_css(CSS_DEFAULT);
    }
    if (empty($css)) {
        return FALSE;
    }
    // Get useful info.
    list($preprocess_css, $scheme, $query_string) = advagg_process_css_js_prep($noagg, 'css');
    // Invoke hook_advagg_css_pre_alter() to give installed modules a chance to
    // modify the data in the $javascript array if necessary.
    drupal_alter('advagg_css_pre', $css, $preprocess_css, $scheme);
    // Set variables.
    $external_no_preprocess = array();
    $module_no_preprocess = array();
    $output_no_preprocess = array();
    $output_preprocess = array();
    $theme_no_preprocess = array();
    $inline_no_preprocess = array();
    $files_included = array();
    $files_aggregates_included = array();
    $inline_included = array();
    // Process input.
    foreach ($css as $media => $types) {
        // Setup some variables
        $files_included[$media] = array();
        $files_aggregates_included[$media] = array();
        $inline_included[$media] = array();
        // If CSS preprocessing is off, we still need to output the styles.
        // Additionally, go through any remaining styles if CSS preprocessing is on
        // and output the non-cached ones.
        foreach ($types as $type => $files) {
            if ($type == 'module') {
                // Setup theme overrides for module styles.
                $theme_styles = array();
                foreach (array_keys($css[$media]['theme']) as $theme_style) {
                    $theme_styles[] = basename($theme_style);
                }
            }
            foreach ($types[$type] as $file => $preprocess) {
                // If the theme supplies its own style using the name of the module
                // style, skip its inclusion. This includes any RTL styles associated
                // with its main LTR counterpart.
                if ($type == 'module' && in_array(str_replace('-rtl.css', '.css', basename($file)), $theme_styles)) {
                    // Unset the file to prevent its inclusion when CSS aggregation is enabled.
                    unset($types[$type][$file]);
                    continue;
                }
                // If a CSS file is not to be preprocessed and it's an inline CSS blob
                // it needs to *always* appear at the *very bottom*.
                if ($type == 'inline') {
                    if (is_array($preprocess)) {
                        foreach ($preprocess as $suffix => $blob) {
                            $blob = advagg_drupal_load_stylesheet_content($blob, $preprocess);
                            // Invoke hook_advagg_css_inline_alter() to give installed modules
                            // a chance to modify the contents of $blob if necessary.
                            drupal_alter('advagg_css_inline', $blob);
                            $inline_no_preprocess[] = array(
                                'media' => $media,
                                'data' => $blob,
                                'prefix' => $file,
                                'suffix' => $suffix,
                            );
                            $inline_included[$media][] = $blob;
                        }
                    }
                    // Unset to prevent its inclusion.
                    unset($types[$type][$file]);
                    continue;
                }
                $prefix = '';
                $suffix = '';
                // Invoke hook_advagg_css_extra_alter() to
                // give installed modules a chance to modify the prefix or suffix for a
                // given filename.
                $values = array(
                    $file,
                    NULL,
                    $prefix,
                    $suffix,
                );
                drupal_alter('advagg_css_extra', $values);
                list($file, $null, $prefix, $suffix) = $values;
                if ($type == 'inline') {
                    $file = advagg_drupal_load_stylesheet_content($file, $preprocess);
                    // Invoke hook_advagg_css_inline_alter() to give installed modules a
                    // chance to modify the contents of $file if necessary.
                    drupal_alter('advagg_css_inline', $file);
                    $inline_no_preprocess[] = array(
                        'media' => $media,
                        'data' => $file,
                        'prefix' => $prefix,
                        'suffix' => $suffix,
                    );
                    $inline_included[$media][] = $file;
                    // Unset to prevent its inclusion.
                    unset($types[$type][$file]);
                    continue;
                }
                // If a CSS file is not to be preprocessed and it's an external
                // CSS file, it needs to *always* appear at the *very top*,
                // regardless of whether preprocessing is on or off.
                if ($type == 'external') {
                    $external_no_preprocess[] = array(
                        'media' => $media,
                        'href' => $file,
                        'prefix' => $prefix,
                        'suffix' => $suffix,
                    );
                    $files_included[$media][$file] = TRUE;
                    // Unset the file to prevent its inclusion.
                    unset($types[$type][$file]);
                    continue;
                }
                // Only include the stylesheet if it exists.
                if (advagg_file_exists($file)) {
                    if (!$preprocess || !($scheme === 'public' && $preprocess_css)) {
                        // Create URI for file.
                        $file_uri = advagg_build_uri($file) . $query_string;
                        $files_included[$media][$file] = $preprocess;
                        // If a CSS file is not to be preprocessed and it's a module CSS
                        // file, it needs to *always* appear at the *top*, regardless of
                        // whether preprocessing is on or off.
                        if (!$preprocess && $type == 'module') {
                            $module_no_preprocess[] = array(
                                'media' => $media,
                                'href' => $file_uri,
                                'prefix' => $prefix,
                                'suffix' => $suffix,
                            );
                        }
                        elseif (!$preprocess && $type == 'theme') {
                            $theme_no_preprocess[] = array(
                                'media' => $media,
                                'href' => $file_uri,
                                'prefix' => $prefix,
                                'suffix' => $suffix,
                            );
                        }
                        else {
                            $output_no_preprocess[] = array(
                                'media' => $media,
                                'href' => $file_uri,
                                'prefix' => $prefix,
                                'suffix' => $suffix,
                            );
                        }
                    }
                }
            }
        }
        if ($scheme == 'public' && $preprocess_css) {
            $files_aggregates_included[$media] = $files_included[$media];
            $files = array();
            foreach ($types as $type) {
                foreach ($type as $file => $cache) {
                    if ($cache) {
                        $files[] = $file;
                        $files_included[$media][$file] = TRUE;
                        unset($files_aggregates_included[$file]);
                    }
                }
            }
            if (!empty($files)) {
                $preprocess_files = advagg_css_js_file_builder('css', $files, $query_string);
                if (!empty($preprocess_files)) {
                    $good = TRUE;
                    foreach ($preprocess_files as $preprocess_file => $extra) {
                        // Empty aggregate, skip
                        if (empty($preprocess_file)) {
                            continue;
                        }
                        if ($extra !== FALSE && is_array($extra)) {
                            $prefix = $extra['prefix'];
                            $suffix = $extra['suffix'];
                            $output_preprocess[] = array(
                                'media' => $media,
                                'href' => advagg_build_uri($preprocess_file),
                                'prefix' => $prefix,
                                'suffix' => $suffix,
                            );
                            $files_aggregates_included[$media][$preprocess_file] = $extra;
                        }
                        else {
                            $good = FALSE;
                            break;
                        }
                    }
                }
                if (empty($good)) {
                    // Redo with aggregation turned off and return the new value.
                    watchdog('advagg', 'CSS aggregation failed. %filename could not be saved correctly.', array(
                        '%filename' => $preprocess_file,
                    ), WATCHDOG_ERROR);
                    $data = advagg_process_css($original_css, TRUE);
                    return $data;
                }
            }
        }
    }
    // Default function called: advagg_unlimited_css_builder
    $function = variable_get('advagg_css_render_function', ADVAGG_CSS_RENDER_FUNCTION);
    return $function($external_no_preprocess, $module_no_preprocess, $output_no_preprocess, $output_preprocess, $theme_no_preprocess, $inline_no_preprocess, $inline_included, $files_included, $files_aggregates_included);
}

/**
 * Logic to figure out what kind of css tags to use.
 *
 * @param $external_no_preprocess
 *   array of css files ($media, $href, $prefix, $suffix)
 * @param $module_no_preprocess
 *   array of css files ($media, $href, $prefix, $suffix)
 * @param $output_no_preprocess
 *   array of css files ($media, $href, $prefix, $suffix)
 * @param $output_preprocess
 *   array of css files ($media, $href, $prefix, $suffix)
 * @param $theme_no_preprocess
 *   array of css files ($media, $href, $prefix, $suffix)
 * @param $inline_no_preprocess
 *   array of css data to inline ($media, $data)
 * @param $inline_included
 *   array of inline css included. $a[$media][] = $datablob;
 * @param $files_included
 *   array of css files included. $a[$media][] = $filename
 * @param $files_aggregates_included
 *   array of css files & aggregates included. $a[$media][] = $filename
 * @return
 *   html for loading the css. html for the head.
 */
function advagg_unlimited_css_builder($external_no_preprocess, $module_no_preprocess, $output_no_preprocess, $output_preprocess, $theme_no_preprocess, $inline_no_preprocess, $files_included, $files_aggregates_included, $inline_included) {
    global $user;
    $styles = '';
    $files = array_merge($external_no_preprocess, $module_no_preprocess, $output_no_preprocess, $output_preprocess, $theme_no_preprocess, $inline_no_preprocess);
    // Select method for css html output
    if (count($files) < variable_get('advagg_css_count_threshold', ADVAGG_CSS_COUNT_THRESHOLD)) {
        advagg_unlimited_css_traditional($files, $styles);
    }
    elseif (variable_get('advagg_css_logged_in_ie_detect', ADVAGG_CSS_LOGGED_IN_IE_DETECT) && $user->uid != 0) {
        // Detect IE browsers here
        $is_ie = FALSE;
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
            // Strings for testing found via
            // http://chrisschuld.com/projects/browser-php-detecting-a-users-browser-from-php/
            // Test for v1 - v1.5 IE
            // Test for versions > 1.5
            // Test for Pocket IE
            if (stristr($_SERVER['HTTP_USER_AGENT'], 'microsoft internet explorer') || stristr($_SERVER['HTTP_USER_AGENT'], 'msie') || stristr($_SERVER['HTTP_USER_AGENT'], 'mspie')) {
                $is_ie = TRUE;
            }
        }
        else {
            $is_ie = TRUE;
        }
        if ($is_ie) {
            advagg_unlimited_css_import(array_merge($external_no_preprocess, $module_no_preprocess, $output_no_preprocess), $styles);
            advagg_unlimited_css_import($output_preprocess, $styles);
            advagg_unlimited_css_import($theme_no_preprocess, $styles);
            advagg_unlimited_css_traditional($inline_no_preprocess, $styles);
        }
        else {
            advagg_unlimited_css_traditional($files, $styles);
        }
    }
    else {
        advagg_unlimited_css_import(array_merge($external_no_preprocess, $module_no_preprocess, $output_no_preprocess), $styles);
        advagg_unlimited_css_import($output_preprocess, $styles);
        advagg_unlimited_css_import($theme_no_preprocess, $styles);
        advagg_unlimited_css_traditional($inline_no_preprocess, $styles);
    }
    return $styles;
}

/**
 * Use link tags for CSS
 *
 * @param $files
 *   array of css files ($media, $href, $prefix, $suffix)
 * @param &$styles
 *   html string
 */
function advagg_unlimited_css_traditional($files, &$styles) {
    $last_prefix = '';
    $last_suffix = '';
    foreach ($files as $css_file) {
        $media = $css_file['media'];
        $prefix = empty($css_file['prefix']) ? '' : $css_file['prefix'] . "\n";
        $suffix = empty($css_file['suffix']) ? '' : $css_file['suffix'];
        // Group prefixes and suffixes.
        if (isset($css_file['href'])) {
            $href = $css_file['href'];
            if ($prefix != $last_prefix) {
                $styles .= $last_suffix . "\n" . $prefix . '<link type="text/css" rel="stylesheet" media="' . $media . '" href="' . $href . '" />' . "\n";
            }
            else {
                $styles .= '<link type="text/css" rel="stylesheet" media="' . $media . '" href="' . $href . '" />' . "\n";
            }
        }
        else {
            $data = $css_file['data'];
            if ($prefix != $last_prefix) {
                $styles .= $last_suffix . "\n" . $prefix . '<style type="text/css" media="' . $media . '">' . "\n" . $data . "\n" . '</style>' . "\n";
            }
            else {
                $styles .= '<style type="text/css" media="' . $media . '">' . "\n" . $data . "\n" . '</style>' . "\n";
            }
        }
        $last_prefix = $prefix;
        $last_suffix = $suffix;
    }
    $styles .= empty($last_suffix) ? '' : $last_suffix . "\n";
}

/**
 * Use import tags for CSS
 *
 * @param $files
 *   array of css files ($media, $href)
 * @param &$styles
 *   html string
 */
function advagg_unlimited_css_import($files, &$styles) {
    $counter = 0;
    $media = NULL;
    $import = '';
    foreach ($files as $css_file) {
        $media_new = $css_file['media'];
        $href = $css_file['href'];
        if ($media_new != $media || $counter > variable_get('advagg_css_count_threshold', ADVAGG_CSS_COUNT_THRESHOLD)) {
            if ($media && !empty($import)) {
                $styles .= "\n" . '<style type="text/css" media="' . $media . '">' . "\n" . $import . '</style>';
                $import = '';
            }
            $counter = 0;
            $media = $media_new;
        }
        $import .= '@import "' . $href . '";' . "\n";
        $counter++;
    }
    if ($media && !empty($import)) {
        $styles .= "\n" . '<style type="text/css" media="' . $media . '">' . "\n" . $import . '</style>';
    }
}

Functions

Title Deprecated Summary
advagg_process_css Returns a themed representation of all stylesheets that should be attached to the page.
advagg_process_html_css
advagg_unlimited_css_builder Logic to figure out what kind of css tags to use.
advagg_unlimited_css_import Use import tags for CSS
advagg_unlimited_css_traditional Use link tags for CSS