Projet

Général

Profil

Paste
Télécharger (7,66 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / css_injector / css_injector.module @ 87dbc3bf

1
<?php
2

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

    
10

    
11
/**
12
 * Deploy this CSS snippet on every page except the listed pages.
13
 */
14
define('CSS_INJECTOR_PAGES_NOTLISTED', 0);
15

    
16
/**
17
 * Deploy this CSS snippet on only the listed pages.
18
 */
19
define('CSS_INJECTOR_PAGES_LISTED', 1);
20

    
21
/**
22
 * Deploy this CSS snippet only if the associated PHP code returns TRUE.
23
 */
24
define('CSS_INJECTOR_PHP', 2);
25

    
26
/**
27
 * Implements hook_help().
28
 */
29
function css_injector_help($path, $arg) {
30
  $output = '';
31
  switch ($path) {
32
    case 'admin/config/modules#description':
33
      $output .= t('Allows administrators to inject CSS into the page output based on configurable rules.');
34
      break;
35
    case 'admin/config/development/css-injector':
36
      $output .= '<p>' . 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.') . '</p>';
37
      break;
38
  }
39
  return $output;
40
}
41

    
42
/**
43
 * Implements hook_init().
44
 * Checks to see whether any CSS files should be added to the current page,
45
 * based on rules configured by the site administrator.
46
 */
47
function css_injector_init() {
48
  $css_rules = _css_injector_load_rule();
49
  foreach ($css_rules as $css_rule) {
50
    if (!isset($css_rule['enabled']) || $css_rule['enabled']) {
51
      if (_css_injector_evaluate_rule($css_rule)) {
52
        $file_uri = _css_injector_rule_uri($css_rule['crid']);
53
        $theme_rules = unserialize($css_rule['rule_themes']);
54
        global $theme;
55
        if (!is_array($theme_rules) || empty($theme_rules) || in_array($theme, $theme_rules, true)) {
56
          switch ($css_rule['media']) {
57
            case 'all':
58
            case 'screen':
59
            case 'print':
60
              drupal_add_css($file_uri, array('type' => 'file','group' => CSS_THEME,'media' => $css_rule['media'],'preprocess' => $css_rule['preprocess']));
61
              break;
62

    
63
            case 'IE 7':
64
            case 'IE 8':
65
            case 'IE 9':
66
              drupal_add_css($file_uri, array(
67
                'group' => CSS_THEME,
68
                'browsers' => array('IE' => $css_rule['media'], '!IE' => FALSE),
69
                'preprocess' => $css_rule['preprocess'])
70
              );
71
              break;
72

    
73
          }
74
        }
75
      }
76
    }
77

    
78
  }
79
}
80

    
81
/**
82
 * Implements hook_css_alter().
83
 * Since we're trying to give the administrator complete control, we'll move
84
 * CSS that this module has added to a high weight, higher even than the theme's
85
 * CSS files. Currently the weight is 200 + the crid, which is currently higher
86
 * than Bartik's CSS.
87
 *
88
 * @param $css
89
 *   The array of CSS files.
90
 */
91
function css_injector_css_alter(&$css) {
92
  $css_rules = _css_injector_load_rule();
93
  foreach ($css_rules as $css_rule) {
94
    $file_uri = _css_injector_rule_uri($css_rule['crid']);
95
    if (!empty($css[$file_uri])) {
96
      $css[$file_uri]['weight'] = 200 + $css_rule['crid'];
97
    }
98
  }
99
}
100

    
101
/**
102
 * Implements hook_menu().
103
 * Defines menu callbacks for CSS Injector's configuration pages.
104
 */
105
function css_injector_menu() {
106
  $items = array(
107
    'admin/config/development/css-injector' => array(
108
      'title' => 'CSS injector',
109
      'description' => 'Add CSS to the page output based on configurable rules.',
110
      'page callback' => 'drupal_get_form',
111
      'page arguments' => array('css_injector_admin_form'),
112
      'access arguments' => array('administer css injection'),
113
      'file' => 'css_injector.admin.inc',
114
    ),
115
    'admin/config/development/css-injector/edit' => array(
116
      'title' => 'Edit CSS injector rule',
117
      'page callback' => 'drupal_get_form',
118
      'page arguments' => array('css_injector_edit'),
119
      'access arguments' => array('administer css injection'),
120
      'file' => 'css_injector.admin.inc',
121
      'type' => MENU_CALLBACK,
122
    ),
123
    'admin/config/development/css-injector/add' => array(
124
      'title' => 'Add CSS injector rule',
125
      'page callback' => 'drupal_get_form',
126
      'page arguments' => array('css_injector_edit'),
127
      'access arguments' => array('administer css injection'),
128
      'file' => 'css_injector.admin.inc',
129
      'type' => MENU_CALLBACK,
130
    ),
131
    'admin/config/development/css-injector/delete' => array(
132
      'title' => 'Delete CSS injector rule',
133
      'page callback' => 'drupal_get_form',
134
      'page arguments' => array('css_injector_delete_confirm'),
135
      'access arguments' => array('administer css injection'),
136
      'file' => 'css_injector.admin.inc',
137
      'type' => MENU_CALLBACK,
138
    ),
139
  );
140
  return $items;
141
}
142

    
143
/**
144
 * Implements hook_theme().
145
 */
146
function css_injector_theme() {
147
  $items['css_injector_admin_form'] = array(
148
    'render element' => 'form',
149
    'file' => 'css_injector.admin.inc',
150
  );
151
  return $items;
152
}
153

    
154
/**
155
 * Implements hook_permission().
156
 */
157
function css_injector_permission() {
158
  return array(
159
    'administer css injection' => array(
160
      'title' => t('Administer CSS Injection'),
161
    ),
162
  );
163
}
164

    
165
/**
166
 * Helper function to load all CSS injection rules.
167
 */
168
function _css_injector_load_rule($crid = NULL, $reset = FALSE) {
169
  static $rules;
170
  // TODO: Change to drupal_static_fast pattern.
171
  if (!isset($rules) || $reset) {
172
    if (!$reset && ($cache = cache_get('css_injector:rules')) && !empty($cache->data)) {
173
      $rules = $cache->data;
174
    }
175
    else {
176
      $rules = array();
177
      $results = db_query("SELECT * FROM {css_injector_rule}", array(), array('fetch' => PDO::FETCH_ASSOC))->fetchAllAssoc('crid');
178
      foreach ($results as $id => $rule) {
179
        $rules[$id] = $rule;
180
      }
181
      cache_set('css_injector:rules', $rules);
182
    }
183
  }
184

    
185
  if (is_numeric($crid)) {
186
    return $rules[$crid];
187
  }
188
  else {
189
    return $rules;
190
  }
191
}
192

    
193
/**
194
 * Helper function to delete an existing rule and its accompanying file.
195
 */
196
function _css_injector_delete_rule($crid) {
197
  if ($rule = _css_injector_load_rule($crid)) {
198
    file_unmanaged_delete(_css_injector_rule_uri($crid));
199
    db_delete('css_injector_rule')
200
      ->condition('crid', $crid)
201
      ->execute();
202
    drupal_set_message(t('The CSS rule %title has been deleted.', array('%title' => $rule['title'])));
203
  }
204
}
205

    
206
/**
207
 * Helper function to determine whether a rule's conditions are met.
208
 *
209
 * @param $css_rule
210
 *   Array describing the rule.
211
 */
212

    
213
function _css_injector_evaluate_rule($css_rule = array()) {
214
  // Match path if necessary.
215
  if (!empty($css_rule['rule_conditions'])) {
216
    if ($css_rule['rule_type'] < CSS_INJECTOR_PHP) {
217
      $path = drupal_get_path_alias($_GET['q']);
218
      // Compare with the internal and path alias (if any).
219
      $page_match = drupal_match_path($path, $css_rule['rule_conditions']);
220
      if ($path != $_GET['q']) {
221
        $page_match = $page_match || drupal_match_path($_GET['q'], $css_rule['rule_conditions']);
222
      }
223
      // When $css_rule['rule_type'] has a value of
224
      // CSS_INJECTOR_PAGES_NOTLISTED, the rule is matched on
225
      // all pages except those listed in $css_rule['rule_conditions'].
226
      // When set to CSS_INJECTOR_PAGES_LISTED, it is displayed only on those
227
      // pages listed in $css_rule['rule_type'].
228
      $page_match = !($css_rule['rule_type'] xor $page_match);
229
    }
230
    else {
231
      if (module_exists('php')) {
232
        $page_match = php_eval($css_rule['rule_conditions']);
233
      }
234
      else {
235
        $page_match = FALSE;
236
      }
237
    }
238
  }
239
  else {
240
    $page_match = TRUE;
241
  }
242
  return $page_match;
243
}
244

    
245
/**
246
 * Return the URI for a crid.
247
 * @param $crid
248
 *   The integer identifying the CSS Rule ID (crid)
249
 */
250
function _css_injector_rule_uri($crid) {
251
  if (!empty($crid)) {
252
    $uri = 'public://css_injector/css_injector_' . $crid . '.css';
253
    return $uri;
254
  }
255
}