Projet

Général

Profil

Paste
Télécharger (14,2 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / themes / bootstrap / includes / alter.inc @ 4eeb3b46

1
<?php
2
/**
3
 * @file
4
 * alter.inc
5
 *
6
 * Contains various implementations of hook_*_alter().
7
 */
8

    
9
/**
10
 * Include #pre_render callbacks for elements.
11
 */
12
bootstrap_include('bootstrap', 'includes/pre-render.inc');
13

    
14
/**
15
 * Include #process callbacks for elements.
16
 */
17
bootstrap_include('bootstrap', 'includes/process.inc');
18

    
19
/**
20
 * Implements hook_css_alter().
21
 */
22
function bootstrap_css_alter(&$css) {
23
  $theme_path = drupal_get_path('theme', 'bootstrap');
24

    
25
  // Exclude specified CSS files from theme.
26
  $excludes = bootstrap_get_theme_info(NULL, 'exclude][css');
27

    
28
  // Add CDN assets, if any.
29
  $provider = bootstrap_setting('cdn_provider');
30
  if ($cdn_assets = bootstrap_get_cdn_assets('css', $provider)) {
31
    $cdn_weight = -2.99;
32
    foreach ($cdn_assets as $cdn_asset) {
33
      $cdn_weight += .01;
34
      $css[$cdn_asset] = array(
35
        'data' => $cdn_asset,
36
        'type' => 'external',
37
        'every_page' => TRUE,
38
        'media' => 'all',
39
        'preprocess' => FALSE,
40
        'group' => CSS_THEME,
41
        'browsers' => array('IE' => TRUE, '!IE' => TRUE),
42
        'weight' => $cdn_weight,
43
      );
44
    }
45

    
46
    // Add a specific version and theme CSS overrides file.
47
    $version = bootstrap_setting('cdn_' . $provider . '_version');
48
    if (!$version) {
49
      $version = BOOTSTRAP_VERSION;
50
    }
51
    $theme = bootstrap_setting('cdn_' . $provider . '_theme');
52
    if (!$theme) {
53
      $theme = 'bootstrap';
54
    }
55
    $theme = $theme === 'bootstrap' || $theme === 'bootstrap_theme' ? '' : "-$theme";
56
    $overrides = "$theme_path/css/$version/overrides$theme.min.css";
57
    if (file_exists($overrides)) {
58
      $css[$overrides] = array(
59
        'data' => $overrides,
60
        'type' => 'file',
61
        'every_page' => TRUE,
62
        'media' => 'all',
63
        'preprocess' => TRUE,
64
        'group' => CSS_THEME,
65
        'browsers' => array('IE' => TRUE, '!IE' => TRUE),
66
        'weight' => -1,
67
      );
68
    }
69
  }
70
  if (!empty($excludes)) {
71
    $excludes = array_merge($excludes, str_replace('.css', '-rtl.css', $excludes));
72
    $css = array_diff_key($css, drupal_map_assoc($excludes));
73
  }
74
}
75

    
76
/**
77
 * Implements hook_element_info_alter().
78
 */
79
function bootstrap_element_info_alter(&$info) {
80
  global $theme_key;
81

    
82
  $cid = "theme_registry:bootstrap:element_info";
83
  $cached = array();
84
  if (($cache = cache_get($cid)) && !empty($cache->data)) {
85
    $cached = $cache->data;
86
  }
87

    
88
  $themes = _bootstrap_get_base_themes($theme_key, TRUE);
89
  foreach ($themes as $theme) {
90
    if (!isset($cached[$theme])) {
91
      $cached[$theme] = array();
92
      foreach (array_keys($info) as $type) {
93
        $element = array();
94

    
95
        // Replace fieldset theme implementations with bootstrap_panel.
96
        if (!empty($info[$type]['#theme']) && $info[$type]['#theme'] === 'fieldset') {
97
          $element['#bootstrap_replace']['#theme'] = 'bootstrap_panel';
98
        }
99
        if (!empty($info[$type]['#theme_wrappers']) && array_search('fieldset', $info[$type]['#theme_wrappers']) !== FALSE) {
100
          $element['#bootstrap_replace']['#theme_wrappers']['fieldset'] = 'bootstrap_panel';
101
        }
102

    
103
        // Setup a default "icon" variable. This allows #icon to be passed
104
        // to every template and theme function.
105
        // @see https://drupal.org/node/2219965
106
        $element['#icon'] = NULL;
107
        $element['#icon_position'] = 'before';
108

    
109
        $properties = array(
110
          '#process' => array(
111
            'form_process',
112
            'form_process_' . $type,
113
          ),
114
          '#pre_render' => array(
115
            'pre_render',
116
            'pre_render_' . $type,
117
          ),
118
        );
119
        foreach ($properties as $property => $callbacks) {
120
          foreach ($callbacks as $callback) {
121
            $function = $theme . '_' . $callback;
122
            if (function_exists($function)) {
123
              // Replace direct core function correlation.
124
              if (!empty($info[$type][$property]) && array_search($callback, $info[$type][$property]) !== FALSE) {
125
                $element['#bootstrap_replace'][$property][$callback] = $function;
126
              }
127
              // Check for a "form_" prefix instead (for #pre_render).
128
              elseif (!empty($info[$type][$property]) && array_search('form_' . $callback, $info[$type][$property]) !== FALSE) {
129
                $element['#bootstrap_replace'][$property]['form_' . $callback] = $function;
130
              }
131
              // Otherwise, append the function.
132
              else {
133
                $element[$property][] = $function;
134
              }
135
            }
136
          }
137
        }
138
        $cached[$theme][$type] = $element;
139
      }
140

    
141
      // Cache the element information.
142
      cache_set($cid, $cached);
143
    }
144

    
145
    // Merge in each theme's cached element info.
146
    $info = _bootstrap_element_info_array_merge($info, $cached[$theme]);
147
  }
148
}
149

    
150
/**
151
 * Merges the cached element information into the runtime array.
152
 *
153
 * @param array $info
154
 *   The element info array to merge data into.
155
 * @param array $cached
156
 *   The cached element info data array to merge from.
157
 *
158
 * @return array
159
 *   The altered element info array.
160
 */
161
function _bootstrap_element_info_array_merge($info, $cached) {
162
  foreach ($cached as $type => $element) {
163
    $replacement_data = isset($element['#bootstrap_replace']) ? $element['#bootstrap_replace'] : array();
164
    unset($element['#bootstrap_replace']);
165
    foreach ($element as $property => $data) {
166
      if (is_array($data)) {
167
        if (!isset($info[$type][$property])) {
168
          $info[$type][$property] = array();
169
        }
170
        // Append the values if not already in the array.
171
        foreach ($data as $key => $value) {
172
          if (!in_array($value, $info[$type][$property])) {
173
            $info[$type][$property][] = $value;
174
          }
175
        }
176
      }
177
      // Create the property, if not already set.
178
      elseif (!isset($info[$type][$property])) {
179
        $info[$type][$property] = $data;
180
      }
181
    }
182
    // Replace data, if necessary.
183
    foreach ($replacement_data as $property => $data) {
184
      if (is_array($data)) {
185
        foreach ($data as $needle => $replacement) {
186
          if (!empty($info[$type][$property]) && ($key = array_search($needle, $info[$type][$property])) !== FALSE) {
187
            $info[$type][$property][$key] = $replacement;
188
          }
189
        }
190
      }
191
      // Replace the property with the new data.
192
      else {
193
        $info[$type][$property] = $data;
194
      }
195
    }
196
  }
197

    
198
  // Return the altered element info array.
199
  return $info;
200
}
201

    
202
/**
203
 * Implements hook_form_alter().
204
 */
205
function bootstrap_form_alter(array &$form, array &$form_state = array(), $form_id = NULL) {
206
  if ($form_id) {
207
    switch ($form_id) {
208
      case 'system_theme_settings':
209
        // Create vertical tabs for global settings (provided by core or other
210
        // contrib modules).
211
        if (!isset($form['global'])) {
212
          $form['global'] = array(
213
            '#type' => 'vertical_tabs',
214
            '#weight' => -9,
215
          );
216
          if (!empty($form_state['build_info']['args'][0])) {
217
            $form['global']['#prefix'] = '<h2><small>' . t('Override Global Settings') . '</small></h2>';
218
          }
219
        }
220

    
221
        // Iterate over all child elements and check to see if they should be
222
        // moved in the global vertical tabs.
223
        $global_children = element_children($form);
224
        foreach ($global_children as $child) {
225
          if (isset($form[$child]['#type']) && $form[$child]['#type'] === 'fieldset' && !isset($form[$child]['#group'])) {
226
            $form[$child]['#group'] = 'global';
227
          }
228
        }
229
        break;
230

    
231
      case 'search_form':
232
        // Add a clearfix class so the results don't overflow onto the form.
233
        $form['#attributes']['class'][] = 'clearfix';
234

    
235
        // Remove container-inline from the container classes.
236
        $form['basic']['#attributes']['class'] = array();
237

    
238
        // Hide the default button from display.
239
        $form['basic']['submit']['#attributes']['class'][] = 'element-invisible';
240

    
241
        // Implement a theme wrapper to add a submit button containing a search
242
        // icon directly after the input element.
243
        $form['basic']['keys']['#theme_wrappers'] = array('bootstrap_search_form_wrapper');
244
        $form['basic']['keys']['#title'] = '';
245
        $form['basic']['keys']['#attributes']['placeholder'] = t('Search');
246
        break;
247

    
248
      case 'search_block_form':
249
        $form['#attributes']['class'][] = 'form-search';
250

    
251
        $form['search_block_form']['#title'] = '';
252
        $form['search_block_form']['#attributes']['placeholder'] = t('Search');
253

    
254
        // Hide the default button from display and implement a theme wrapper
255
        // to add a submit button containing a search icon directly after the
256
        // input element.
257
        $form['actions']['submit']['#attributes']['class'][] = 'element-invisible';
258
        $form['search_block_form']['#theme_wrappers'] = array('bootstrap_search_form_wrapper');
259

    
260
        // Apply a clearfix so the results don't overflow onto the form.
261
        $form['#attributes']['class'][] = 'content-search';
262
        break;
263

    
264
      case 'image_style_form':
265
        $form['effects']['new']['new']['#input_group_button'] = TRUE;
266
        break;
267

    
268
      case 'path_admin_filter_form':
269
        $form['basic']['filter']['#input_group_button'] = TRUE;
270
        break;
271
    }
272

    
273
  }
274
}
275

    
276
/**
277
 * Implements hook_js_alter().
278
 */
279
function bootstrap_js_alter(&$js) {
280
  // Exclude specified JavaScript files from theme.
281
  $excludes = bootstrap_get_theme_info(NULL, 'exclude][js');
282

    
283
  $theme_path = drupal_get_path('theme', 'bootstrap');
284

    
285
  // Add or replace JavaScript files when matching paths are detected.
286
  // Replacement files must begin with '_', like '_node.js'.
287
  $files = _bootstrap_file_scan_directory($theme_path . '/js', '/\.js$/');
288
  foreach ($files as $file) {
289
    $path = str_replace($theme_path . '/js/', '', $file->uri);
290
    // Detect if this is a replacement file.
291
    $replace = FALSE;
292
    if (preg_match('/^[_]/', $file->filename)) {
293
      $replace = TRUE;
294
      $path = dirname($path) . '/' . preg_replace('/^[_]/', '', $file->filename);
295
    }
296
    $matches = array();
297
    if (preg_match('/^modules\/([^\/]*)/', $path, $matches)) {
298
      if (!module_exists($matches[1])) {
299
        continue;
300
      }
301
      else {
302
        $path = str_replace('modules/' . $matches[1], drupal_get_path('module', $matches[1]), $path);
303
      }
304
    }
305
    // Path should always exist to either add or replace JavaScript file.
306
    if (!empty($js[$path])) {
307
      // Replace file.
308
      if ($replace) {
309
        $js[$file->uri] = $js[$path];
310
        $js[$file->uri]['data'] = $file->uri;
311
        unset($js[$path]);
312
      }
313
      // Add file.
314
      else {
315
        $js[$file->uri] = drupal_js_defaults($file->uri);
316
        $js[$file->uri]['group'] = JS_THEME;
317
      }
318
    }
319
  }
320

    
321
  // Ensure jQuery Once is always loaded.
322
  // @see https://drupal.org/node/2149561
323
  if (empty($js['misc/jquery.once.js'])) {
324
    $jquery_once = drupal_get_library('system', 'jquery.once');
325
    $js['misc/jquery.once.js'] = $jquery_once['js']['misc/jquery.once.js'];
326
    $js['misc/jquery.once.js'] += drupal_js_defaults('misc/jquery.once.js');
327
  }
328

    
329
  // Always add bootstrap.js last.
330
  $bootstrap = $theme_path . '/js/bootstrap.js';
331
  $js[$bootstrap] = drupal_js_defaults($bootstrap);
332
  $js[$bootstrap]['group'] = JS_THEME;
333
  $js[$bootstrap]['scope'] = 'footer';
334

    
335
  if (!empty($excludes)) {
336
    $js = array_diff_key($js, drupal_map_assoc($excludes));
337
  }
338

    
339
  // Add Bootstrap settings.
340
  $js['settings']['data'][]['bootstrap'] = array(
341
    'anchorsFix' => bootstrap_setting('anchors_fix'),
342
    'anchorsSmoothScrolling' => bootstrap_setting('anchors_smooth_scrolling'),
343
    'formHasError' => (int) bootstrap_setting('forms_has_error_value_toggle'),
344
    'popoverEnabled' => bootstrap_setting('popover_enabled'),
345
    'popoverOptions' => array(
346
      'animation' => (int) bootstrap_setting('popover_animation'),
347
      'html' => (int) bootstrap_setting('popover_html'),
348
      'placement' => bootstrap_setting('popover_placement'),
349
      'selector' => bootstrap_setting('popover_selector'),
350
      'trigger' => implode(' ', array_filter(array_values((array) bootstrap_setting('popover_trigger')))),
351
      'triggerAutoclose' => (int) bootstrap_setting('popover_trigger_autoclose'),
352
      'title' => bootstrap_setting('popover_title'),
353
      'content' => bootstrap_setting('popover_content'),
354
      'delay' => (int) bootstrap_setting('popover_delay'),
355
      'container' => bootstrap_setting('popover_container'),
356
    ),
357
    'tooltipEnabled' => bootstrap_setting('tooltip_enabled'),
358
    'tooltipOptions' => array(
359
      'animation' => (int) bootstrap_setting('tooltip_animation'),
360
      'html' => (int) bootstrap_setting('tooltip_html'),
361
      'placement' => bootstrap_setting('tooltip_placement'),
362
      'selector' => bootstrap_setting('tooltip_selector'),
363
      'trigger' => implode(' ', array_filter(array_values((array) bootstrap_setting('tooltip_trigger')))),
364
      'delay' => (int) bootstrap_setting('tooltip_delay'),
365
      'container' => bootstrap_setting('tooltip_container'),
366
    ),
367
  );
368

    
369
  // Add CDN assets, if any.
370
  if ($cdn_assets = bootstrap_get_cdn_assets('js')) {
371
    $cdn_weight = -99.99;
372
    foreach ($cdn_assets as $cdn_asset) {
373
      $cdn_weight += .01;
374
      $js[$cdn_asset] = drupal_js_defaults($cdn_asset);
375
      $js[$cdn_asset]['type'] = 'external';
376
      $js[$cdn_asset]['every_page'] = TRUE;
377
      $js[$cdn_asset]['weight'] = $cdn_weight;
378
    }
379
  }
380
}
381

    
382
/**
383
 * Implements hook_icon_bundle_list_alter().
384
 */
385
function bootstrap_icon_bundle_list_alter(&$build, $bundle) {
386
  if (bootstrap_setting('tooltip_enabled')) {
387
    foreach ($build as &$icon) {
388
      $icon['#attributes']['data-toggle'] = 'tooltip';
389
      $icon['#attributes']['data-placement'] = 'bottom';
390
    }
391
  }
392
}
393

    
394
/**
395
 * Implements hook_menu_local_tasks_alter().
396
 */
397
function bootstrap_menu_local_tasks_alter(&$data, &$router_item, $root_path) {
398
  if (!empty($data['actions']['output'])) {
399
    $items = array();
400
    foreach ($data['actions']['output'] as $item) {
401
      $items[] = array(
402
        'data' => $item,
403
      );
404
    }
405
    $data['actions']['output'] = array(
406
      '#theme' => 'item_list__action_links',
407
      '#items' => $items,
408
      '#attributes' => array(
409
        'class' => array('action-links'),
410
      ),
411
    );
412
  }
413
}
414

    
415
/**
416
 * Implements hook_js_callback_filter_xss_alter().
417
 */
418
function bootstrap_js_callback_filter_xss_alter(array &$allowed_tags = array()) {
419
  $allowed_tags[] = 'button';
420
}