Skip to content
css_injector.module 4.14 KiB
Newer Older
<?php
// $Id

/**
 * @file
 * Allows administrators to inject CSS into the page output based on
 * configurable rules. Useful for adding simple CSS tweaks without modifying
 * a site's official theme.
 */

/**
 * Implementation of 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 (_css_injector_evaluate_rule($css_rule)) {
      drupal_add_css(file_create_path($css_rule['file_path']), 'module', $css_rule['media'], $css_rule['preprocess']);
    }
  }
}

/**
 * Implementation of hook_menu.
 * Defines menu callbacks for CSS Injector's configuration pages.
 */
function css_injector_menu() {
  $items = array(
    'admin/settings/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 callback' => 'user_access',
      'access arguments' => array('administer css injection'),
      'file' => 'css_injector.admin.inc',
    ),
    'admin/settings/css_injector/edit' => array(
      'title' => 'Edit CSS injector rule',
      'page callback' => 'drupal_get_form',
      'page arguments' => array('css_injector_edit'),
      'file' => 'css_injector.admin.inc',
    ),
    'admin/settings/css_injector/add' => array(
      'title' => 'Add CSS injector rule',
      'page callback' => 'drupal_get_form',
      'page arguments' => array('css_injector_edit'),
      'file' => 'css_injector.admin.inc',
    ),
    'admin/settings/css_injector/delete' => array(
      'title' => 'Add CSS injector rule',
      'page callback' => 'drupal_get_form',
      'page arguments' => array('css_injector_delete_confirm'),
      'file' => 'css_injector.admin.inc',
    ),
  );
  return $items;
}

function css_injector_theme() {
  $items['css_injector_admin_form'] = array(
    'arguments' => array('form' => array()),
    'file' => 'css_injector.admin.inc',
  );
  return $items;
}

function css_injector_perm() {
  return array('administer css injection');
}

/**
 * Helper function to load all CSS injection rules
 */
function _css_injector_load_rule($crid = NULL, $reset = FALSE) {
  static $rules;
  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}");
      while ($rule = db_fetch_array($results)) {
        $rules[$rule['crid']] = $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_delete(file_create_path($rule['file_path']));
    db_query("DELETE FROM {css_injector_rule} WHERE crid = %d", $crid);
  }
}

/**
 * Helper function to determine whether a rule's conditions are met
 */
function _css_injector_evaluate_rule($css_rule = array()) {
  // Match path if necessary
  if (!empty($css_rule['rule_conditions'])) {
    if ($css_rule['rule_type'] < 2) {
      $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 0, the rule is matched on
      // all pages except those listed in $css_rule['rule_conditions']. When set to 1, it
      // is displayed only on those pages listed in $css_rule['rule_type'].
      $page_match = !($css_rule['rule_type'] xor $page_match);
    }
    else {
      $page_match = drupal_eval($css_rule['rule_conditions']);
    }
  }
  else {
    $page_match = TRUE;
  }
  return $page_match;
}