' . t('Use CSS injection rules to add small snippets of CSS to the page output when specific criteria are met. For example, a simple rule could change the page background color at night or float a particular div to the right on node editing pages.') . '

'; break; } return $output; } /** * Implements hook_init(). * Checks to see whether any CSS files should be added to the current page, * based on rules configured by the site administrator. */ function css_injector_init() { $css_rules = _css_injector_load_rule(); foreach ($css_rules as $css_rule) { if (!isset($css_rule['enabled']) || $css_rule['enabled']) { if (_css_injector_evaluate_rule($css_rule)) { $file_uri = _css_injector_rule_uri($css_rule['crid']); $theme_rules = unserialize($css_rule['rule_themes']); global $theme; if (!is_array($theme_rules) || empty($theme_rules) || in_array($theme, $theme_rules, true)) { switch ($css_rule['media']) { case 'all': case 'screen': case 'print': drupal_add_css($file_uri, array('type' => 'file','group' => CSS_THEME,'media' => $css_rule['media'],'preprocess' => $css_rule['preprocess'])); break; case 'IE 7': case 'IE 8': case 'IE 9': drupal_add_css($file_uri, array( 'group' => CSS_THEME, 'browsers' => array('IE' => $css_rule['media'], '!IE' => FALSE), 'preprocess' => $css_rule['preprocess']) ); break; } } } } } } /** * Implements hook_css_alter(). * Since we're trying to give the administrator complete control, we'll move * CSS that this module has added to a high weight, higher even than the theme's * CSS files. Currently the weight is 200 + the crid, which is currently higher * than Bartik's CSS. * * @param $css * The array of CSS files. */ function css_injector_css_alter(&$css) { $css_rules = _css_injector_load_rule(); foreach ($css_rules as $css_rule) { $file_uri = _css_injector_rule_uri($css_rule['crid']); if (!empty($css[$file_uri])) { $css[$file_uri]['weight'] = 200 + $css_rule['crid']; } } } /** * Implements hook_menu(). * Defines menu callbacks for CSS Injector's configuration pages. */ function css_injector_menu() { $items = array( 'admin/config/development/css-injector' => array( 'title' => 'CSS injector', 'description' => 'Add CSS to the page output based on configurable rules.', 'page callback' => 'drupal_get_form', 'page arguments' => array('css_injector_admin_form'), 'access arguments' => array('administer css injection'), 'file' => 'css_injector.admin.inc', ), 'admin/config/development/css-injector/edit' => array( 'title' => 'Edit CSS injector rule', 'page callback' => 'drupal_get_form', 'page arguments' => array('css_injector_edit'), 'access arguments' => array('administer css injection'), 'file' => 'css_injector.admin.inc', 'type' => MENU_CALLBACK, ), 'admin/config/development/css-injector/add' => array( 'title' => 'Add CSS injector rule', 'page callback' => 'drupal_get_form', 'page arguments' => array('css_injector_edit'), 'access arguments' => array('administer css injection'), 'file' => 'css_injector.admin.inc', 'type' => MENU_CALLBACK, ), 'admin/config/development/css-injector/delete' => array( 'title' => 'Delete CSS injector rule', 'page callback' => 'drupal_get_form', 'page arguments' => array('css_injector_delete_confirm'), 'access arguments' => array('administer css injection'), 'file' => 'css_injector.admin.inc', 'type' => MENU_CALLBACK, ), ); return $items; } /** * Implements hook_theme(). */ function css_injector_theme() { $items['css_injector_admin_form'] = array( 'render element' => 'form', 'file' => 'css_injector.admin.inc', ); return $items; } /** * Implements hook_permission(). */ function css_injector_permission() { return array( 'administer css injection' => array( 'title' => t('Administer CSS Injection'), ), ); } /** * Helper function to load all CSS injection rules. */ function _css_injector_load_rule($crid = NULL, $reset = FALSE) { static $rules; // TODO: Change to drupal_static_fast pattern. if (!isset($rules) || $reset) { if (!$reset && ($cache = cache_get('css_injector:rules')) && !empty($cache->data)) { $rules = $cache->data; } else { $rules = array(); $results = db_query("SELECT * FROM {css_injector_rule}", array(), array('fetch' => PDO::FETCH_ASSOC))->fetchAllAssoc('crid'); foreach ($results as $id => $rule) { $rules[$id] = $rule; } cache_set('css_injector:rules', $rules); } } if (is_numeric($crid)) { return $rules[$crid]; } else { return $rules; } } /** * Helper function to delete an existing rule and its accompanying file. */ function _css_injector_delete_rule($crid) { if ($rule = _css_injector_load_rule($crid)) { file_unmanaged_delete(_css_injector_rule_uri($crid)); db_delete('css_injector_rule') ->condition('crid', $crid) ->execute(); drupal_set_message(t('The CSS rule %title has been deleted.', array('%title' => $rule['title']))); } } /** * Helper function to determine whether a rule's conditions are met. * * @param $css_rule * Array describing the rule. */ function _css_injector_evaluate_rule($css_rule = array()) { // Match path if necessary. if (!empty($css_rule['rule_conditions'])) { if ($css_rule['rule_type'] < CSS_INJECTOR_PHP) { $path = drupal_get_path_alias($_GET['q']); // Compare with the internal and path alias (if any). $page_match = drupal_match_path($path, $css_rule['rule_conditions']); if ($path != $_GET['q']) { $page_match = $page_match || drupal_match_path($_GET['q'], $css_rule['rule_conditions']); } // When $css_rule['rule_type'] has a value of // CSS_INJECTOR_PAGES_NOTLISTED, the rule is matched on // all pages except those listed in $css_rule['rule_conditions']. // When set to CSS_INJECTOR_PAGES_LISTED, it is displayed only on those // pages listed in $css_rule['rule_type']. $page_match = !($css_rule['rule_type'] xor $page_match); } else { if (module_exists('php')) { $page_match = php_eval($css_rule['rule_conditions']); } else { $page_match = FALSE; } } } else { $page_match = TRUE; } return $page_match; } /** * Return the URI for a crid. * @param $crid * The integer identifying the CSS Rule ID (crid) */ function _css_injector_rule_uri($crid) { if (!empty($crid)) { $uri = 'public://css_injector/css_injector_' . $crid . '.css'; return $uri; } }