Projet

Général

Profil

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

root / drupal7 / sites / all / modules / variable / variable_realm / variable_realm.module @ 6331c987

1
<?php
2
/**
3
 * @file
4
 * Variable API module - Realms
5
 *
6
 * Each variable realm can be in one of four states.
7
 * - Undefined, The realm controller has not been created yet.
8
 * - Defined, The realm controller has been created.
9
 * - Enabled, A value has been set for the realm key, though it may be disabled (FALSE)
10
 * - Active, The realm key has been set and is not FALSE.
11
 */
12

    
13
// Prefix for realm keys on query string.
14
define('VARIABLE_REALM_QUERY_STRING', 'variable_realm_key_');
15
// Prefix for realm switcher element in forms.
16
define('VARIABLE_REALM_FORM_SWITCHER', 'variable_realm_selector_');
17

    
18
/**
19
 * Implements hook_boot()
20
 *
21
 * We set current variable realms as early as possible in the page request.
22
 */
23
function variable_realm_boot() {
24
  variable_realm_status('global', 'default');
25
  variable_realm_rebuild();
26
}
27

    
28
/**
29
 * Implements hook_init()
30
 *
31
 * Let realms be overriden by query string parameters, but only for:
32
 * - Admin paths (not variable realm admin pages)
33
 */
34
function variable_realm_init() {
35
  if (arg(0) == 'admin' && (arg(3) != 'variable' || arg(4) != 'realm') && ($params = variable_realm_params()) && user_access('administer site configuration')) {
36
    foreach ($params as $realm_name => $realm_key) {
37
      variable_realm_switch($realm_name, $realm_key, FALSE);
38
    }
39
    variable_realm_rebuild();
40
  }
41
}
42

    
43
/**
44
 * Initialize realm and set key depending on request.
45
 *
46
 * @param $realm_name
47
 *   Variable realm name.
48
 * @param $realm_key
49
 *   Optional key to be set when we don't have other key.
50
 */
51
function variable_realm_initialize($realm_name, $realm_key = NULL) {
52
  $realm_controller = variable_realm_controller($realm_name);
53
  if ($realm_controller && !$realm_controller->isEnabled()) {
54
    $new_key = $realm_controller->enable($realm_key);
55
    _variable_realm_invoke_all('variable_realm_enable', $realm_name, $new_key);
56
    _variable_realm_hook('variableRealmEnable', $realm_name, $new_key);
57
    // If we have already built the configuration, rebuild it.
58
    if ($new_key && drupal_static('variable_realm_rebuild')) {
59
      variable_realm_rebuild();
60
    }
61
  }
62
}
63

    
64
/**
65
 * Get list of all available realm names ordered by default weight.
66
 */
67
function variable_realm_list() {
68
  return _variable_realm_invoke(variable_realm_list_all(), 'getTitle');
69
}
70

    
71
/**
72
 * Get all available realm controllers ordered by default weight.
73
 */
74
function variable_realm_list_all() {
75
  $list = array();
76
  foreach (array_keys(variable_realm_info()) as $name) {
77
    if ($controller = variable_realm_controller($name)) {
78
      $list[$name] = $controller;
79
    }
80
    uasort($list, '_variable_realm_sort_default');
81
  }
82
  return $list;
83
}
84

    
85
/**
86
 * Get realm parameters from query string.
87
 */
88
function variable_realm_params($realm_name = NULL) {
89
  $realm_params = &drupal_static(__FUNCTION__);
90
  if (!isset($realm_params)) {
91
    $realm_params = array();
92
    foreach (variable_realm_info() as $realm => $realm_info) {
93
      if (!empty($realm_info['form switcher'])) {
94
        $param = VARIABLE_REALM_QUERY_STRING . $realm;
95
        if (!empty($_GET[$param]) && array_key_exists($_GET[$param], variable_realm_keys($realm))) {
96
          $realm_params[$realm] = $_GET[$param];
97
        }
98
      }
99
    }
100
  }
101
  if ($realm_name) {
102
    return isset($realm_params[$realm_name]) ? $realm_params[$realm_name] : FALSE;
103
  }
104
  else {
105
    return $realm_params;
106
  }
107
}
108

    
109

    
110
/**
111
 * Get information about variable realms.
112
 */
113
function variable_realm_info($realm_name = NULL) {
114
  $realm_info_tmp = $realm_info = &drupal_static(__FUNCTION__);
115

    
116
  if (!isset($realm_info_tmp)) {
117
    $realm_info_tmp = _variable_realm_invoke_all('variable_realm_info');
118

    
119
    // If first param is NULL, module_load_all() only returns a boolean
120
    // indicating whether all modules have been loaded.
121
    if (module_load_all(NULL)) {
122
      // Due to the fact that variable_realm_info() gets called by some
123
      // modules and the menu access callbacks early in the bootstrap,
124
      // we could not cache the realm info for later calls until all
125
      // modules have been loaded.
126
      $realm_info = $realm_info_tmp;
127
    }
128
  }
129

    
130
  if ($realm_name) {
131
    return isset($realm_info_tmp[$realm_name]) ? $realm_info_tmp[$realm_name] : array();
132
  }
133
  else {
134
    return $realm_info_tmp;
135
  }
136
}
137

    
138
/**
139
 * Implements hook_variable_realm_info().
140
 */
141
function variable_realm_variable_realm_info() {
142
  $realm['global'] = array(
143
    'title' => t('Global'),
144
    'weight' => 0,
145
    'controller class' => 'VariableRealmDefaultController',
146
    'store class' => 'VariableRealmGlobalStore',
147
    'keys' => array(
148
      'default' => t('All variables')
149
    ),
150
  );
151
  return $realm;
152
}
153

    
154

    
155
/**
156
 * Get keys for realm.
157
 */
158
function variable_realm_keys($realm_name) {
159
  if ($controller = variable_realm_controller($realm_name)) {
160
    return $controller->getAllKeys();
161
  }
162
}
163

    
164
/**
165
 * Get variable realm store.
166
 *
167
 * The first time this function is invoked we initialize the realm system
168
 * and store global variables in the global/default realm.
169
 *
170
 * @param $realm
171
 *   Name of the realm to get / create.
172
 * @param $key
173
 *   Realm key to get / create
174
 *
175
 * @return VariableRealmControllerInterface
176
 */
177
function variable_realm($realm, $key) {
178
  $controller = variable_realm_controller($realm);
179
  return $controller ? $controller->getStore($key) : NULL;
180
}
181

    
182
/**
183
 * Get variable realm controller or create it if not defined.
184
 */
185
function variable_realm_controller($realm_name = NULL) {
186
  static $drupal_static_fast;
187
  if (!isset($drupal_static_fast)) {
188
    $drupal_static_fast['realm'] = &drupal_static(__FUNCTION__, array());
189
    if ($global = _variable_realm_controller('global')) {
190
      $global->addStore('default', $GLOBALS['conf']);
191
      $drupal_static_fast['realm']['global'] = $global;
192
    }
193
  }
194
  $variable_realm = &$drupal_static_fast['realm'];
195

    
196
  if ($realm_name) {
197
    if (!isset($variable_realm[$realm_name])) {
198
      $variable_realm[$realm_name] = _variable_realm_controller($realm_name);
199
    }
200
    return $variable_realm[$realm_name];
201
  }
202
  else {
203
    // Return only existing realms.
204
    return array_filter($variable_realm);
205
  }
206
}
207

    
208
/**
209
 * Get value from realm
210
 */
211
function variable_realm_get($realm, $key, $name = NULL, $default = NULL) {
212
  if ($store = variable_realm($realm, $key)) {
213
    return $store->variable_get($name, $default);
214
  }
215
}
216

    
217
/**
218
 * Set values for variable realm
219
 *
220
 * @param $realm
221
 *   Realm name.
222
 * @param $key
223
 *   Realm key.
224
 * @param $values
225
 *   Array of runtime variable values to add to the realm.
226
 * @param $weight
227
 *   Optional explicit weight for this realm.
228
 * @param $rebuild
229
 *   Whether to rebuild domains immediately
230
 */
231
function variable_realm_add($realm, $key, $values = array(), $weight = NULL, $rebuild = TRUE) {
232
  if ($variable_realm = variable_realm($realm, $key)) {
233
    foreach ($values as $name => $value) {
234
      $variable_realm->variable_add($name, $value);
235
    }
236
    if (isset($weight)) {
237
      variable_realm_weight($realm, $weight);
238
    }
239
    // Rebuild only if this is the current realm
240
    if ($rebuild && variable_realm_status($realm) === $key) {
241
      variable_realm_rebuild();
242
    }
243
  }
244
}
245

    
246
/**
247
 * Set value for realm variable.
248
 */
249
function variable_realm_set($realm, $key, $name, $value, $rebuild = TRUE) {
250
  if ($store = variable_realm($realm, $key)) {
251
    $old_value = variable_realm_get($realm, $key, $name);
252
    $store->variable_set($name, $value);
253
    if ($rebuild) {
254
      variable_realm_refresh($realm, $key, $name);
255
    }
256
    $options = array(
257
      'realm' => $store->realm,
258
      'key' => $store->key,
259
    );
260
    module_invoke_all('variable_update', $name, $value, $old_value, $options);
261
  }
262
}
263

    
264
/**
265
 * Delete variable from realm
266
 */
267
function variable_realm_del($realm, $key, $name, $rebuild = TRUE) {
268
  if ($store = variable_realm($realm, $key)) {
269
    $store->variable_del($name);
270
    if ($rebuild) {
271
      variable_realm_refresh($realm, $key, $name);
272
    }
273
  }
274
}
275

    
276

    
277
/**
278
 * Refresh variable value.
279
 */
280
function variable_realm_refresh($realm_name, $realm_key, $variable_name) {
281
  $value = NULL;
282
  // Only update value if this is the current realm.
283
  if (variable_realm_status($realm_name) === $realm_key) {
284
    foreach (variable_realm_current() as $realm_controller) {
285
      $value = $realm_controller->getCurrentStore()->variable_get($variable_name, $value);
286
    }
287
  }
288
  if (isset($value)) {
289
    $GLOBALS['conf'][$variable_name] = $value;
290
  }
291
  else {
292
    unset($GLOBALS['conf'][$variable_name]);
293
  }
294
}
295

    
296

    
297
/**
298
 * Get active realm controllers ordered by weight.
299
 */
300
function variable_realm_current() {
301
  $active = array_filter(variable_realm_controller(), '_variable_realm_active');
302
  uasort($active, '_variable_realm_sort_current');
303
  return $active;
304
}
305

    
306
/**
307
 * Check whether a realm is defined.
308
 */
309
function variable_realm_defined($realm_name) {
310
  $controllers = variable_realm_controller();
311
  return !empty($controllers[$realm_name]);
312
}
313

    
314
/**
315
 * Get current realm values ordered by weights, only realms that are set.
316
 *
317
 * @return array
318
 *   Ordered array of name => key pairs.
319
 */
320
function variable_realm_current_keys() {
321
  return array_map('_variable_realm_status', variable_realm_current());
322
}
323

    
324
/**
325
 * Get current realm values ordered by weights.
326
 *
327
 * @return array
328
 *   Ordered array of name => value pairs, only realms that are set.
329
 */
330

    
331
/**
332
 * Get original global variable
333
 */
334
function variable_realm_global_get($name, $default = NULL) {
335
  return variable_realm_get('global', 'default', $name, $default);
336
}
337

    
338
/**
339
 * Switch global variable
340
 *
341
 * @param $name
342
 *   Optional global variable name. If not set, it will reset all global variables to its original value.
343
 * @param $value
344
 *   Optional new value for global variable. If not set, it will reset the variable to its original value.
345
 * @param $rebuild
346
 *   Whether to rebuild the current global $conf
347
 */
348
function variable_realm_global_set($name, $value = NULL, $rebuild = TRUE) {
349
  variable_realm_set('global', 'default', $name, $value, $rebuild);
350
}
351

    
352
/**
353
 * Set / get current realm values.
354
 *
355
 * @param $realm
356
 *   Optional realm name
357
 * @param $key
358
 *   Optional realm value to set a status for this realm.
359
 *   FALSE to disable this realm.
360
 */
361
function variable_realm_status($realm, $key = NULL) {
362
  if ($realm_controller = variable_realm_controller($realm)) {
363
    if (isset($key)) {
364
      $realm_controller->setKey($key);
365
    }
366
    return $realm_controller->getKey();
367
  }
368
}
369

    
370
/**
371
 * Switch current variable realms.
372
 *
373
 * @see variable_realm_weight()
374
 *
375
 * @param $realm
376
 *   Realm name. Example 'language'.
377
 * @param $key
378
 *   Realm key. Example, for language will be a language code, 'en
379
 *   FALSE to unset the realm.
380
 * @param $rebuild
381
 *   Whether we need to rebuild the configuration.
382
 */
383
function variable_realm_switch($realm, $key, $rebuild = TRUE) {
384
  // Check previous status, if not changed no need to rebuild.
385
  $current = variable_realm_status($realm);
386
  if (!isset($current) || $current !== $key) {
387
    variable_realm_status($realm, $key);
388
    _variable_realm_invoke_all('variable_realm_switch', $realm, $key);
389
    _variable_realm_hook('variableRealmSwitch', $realm, $key);
390
    if ($rebuild) {
391
      variable_realm_rebuild();
392
    }
393
  }
394
}
395

    
396
/**
397
 * Get / set realm weights.
398
 *
399
 * The default realm will have a weight of 0. Realms with higher weights will override
400
 * global variables.
401
 *
402
 * @param $realm
403
 *   Realm name
404
 * @param $weight
405
 *   Optional numeric value for realm weight.
406
 * @return integer
407
 *   Current realm weight
408
 */
409
function variable_realm_weight($realm, $weight = NULL) {
410
  if ($realm_controller = variable_realm_controller($realm)) {
411
    if (isset($weight)) {
412
      $realm_controller->setWeight($weight);
413
    }
414
    return $realm_controller->getWeight();
415
  }
416
}
417

    
418

    
419
/**
420
 * Rebuild current variable realm.
421
 */
422
function variable_realm_rebuild() {
423
  $rebuild_keys = &drupal_static(__FUNCTION__);
424
  _variable_realm_invoke_all('variable_realm_rebuild');
425
  $rebuild_keys = variable_realm_current_keys();
426
  $GLOBALS['conf'] = _variable_realm_build();
427
}
428

    
429

    
430
/**
431
 * Reset realms, deleting currently set ones
432
 *
433
 * If no parameters passed, it will reset global variables to original values.
434
 *
435
 * @param $realm_keys
436
 *   Array of realm name => realm key to be set.
437
 */
438
function variable_realm_reset($realm_keys = array()) {
439
  // We need at least some value for the global realm
440
  $status = $realm_keys + array('global', 'default');
441
  // Disable current active realms not in the list
442
  foreach (variable_realm_current() as $realm_name => $realm_controller) {
443
    if (!isset($status[$realm_name])) {
444
      variable_realm_switch($realm_name, FALSE, FALSE);
445
    }
446
  }
447
  foreach ($status as $realm_name => $realm_key) {
448
    variable_realm_switch($realm_name, $realm_key, FALSE);
449
  }
450
  variable_realm_rebuild();
451
}
452

    
453

    
454
/**
455
 * Implements hook_variable_delete().
456
 */
457
function variable_realm_variable_delete($variable, $options) {
458
  // If there's a realm option, we are already deleting variable for a realm only.
459
  if (empty($options['realm'])) {
460
    // Delete each variable for each current and existing realm/key
461
    foreach (variable_children($variable['name']) as $variable_name) {
462
      foreach (variable_realm_list_all() as $realm_controller) {
463
        $realm_controller->deleteVariable($variable_name);
464
      }
465
    }
466
    variable_realm_rebuild();
467
  }
468
}
469

    
470
/**
471
 * Implements hook_features_api().
472
 */
473
function variable_realm_features_api() {
474
  $components = array(
475
    'variable_realm' => array(
476
      'name' => t('Realm variables'),
477
      'default_hook' => 'variable_realm_default_variables',
478
      'default_file' => FEATURES_DEFAULTS_CUSTOM,
479
      'default_filename' => 'variable',
480
      'features_source' => TRUE,
481
      'file' => drupal_get_path('module', 'variable_realm') .'/variable_realm.features.inc',
482
    ),
483
  );
484
  return $components;
485
}
486

    
487
/**
488
 * Check whether realm is active.
489
 */
490
function _variable_realm_active($realm_controller) {
491
  return $realm_controller && $realm_controller->isActive();
492
}
493

    
494
/**
495
 * Build current realm.
496
 *
497
 * Buids an array of variables for the current realm with higher weights overriding
498
 * lower weights.
499
 */
500
function _variable_realm_build() {
501
  $variables = array();
502
  foreach (variable_realm_current() as $realm_controller) {
503
    if ($values = $realm_controller->getCurrentVariables()) {
504
      $variables = array_merge($variables, $values);
505
    }
506
  }
507
  return $variables;
508
}
509

    
510
/**
511
 * Invoke method on a list of objects.
512
 */
513
function _variable_realm_invoke($list, $method) {
514
  $result = array();
515
  foreach ($list as $index => $object) {
516
    $result[$index] = $object->$method();
517
  }
518
  return $result;
519
}
520

    
521
/**
522
 * Invokes all realm controllers that implement a method.
523
 *
524
 * @param $method
525
 *   Method name
526
 * @param $arg1, $arg2...
527
 *   Variable number of arguments to pass to the method.
528
 */
529
function _variable_realm_hook() {
530
  $args = func_get_args();
531
  $method = array_shift($args);
532
  $result = array();
533
  foreach (variable_realm_controller() as $realm_name => $realm_controller) {
534
    if (method_exists($realm_controller, $method)) {
535
      $result[$realm_name] = call_user_func_array(array($realm_controller, $method), $args);
536
    }
537
  }
538
  return $result;
539
}
540

    
541
/**
542
 * Create realm controller object.
543
 *
544
 * This may be invoked really early in the bootstrap so it needs to be safe enough
545
 * for module updates and check whether the class really exists. It returns FALSE if not.
546
 */
547
function _variable_realm_controller($realm_name) {
548
  $info = variable_realm_info($realm_name);
549
  $class = !empty($info['controller class']) ? $info['controller class'] : 'VariableRealmDefaultController';
550
  return class_exists($class) ? new $class($realm_name) : FALSE;
551
}
552

    
553
/**
554
 * Get current weight for realm controller.
555
 */
556
function _variable_realm_weight($realm_controller) {
557
  return $realm_controller->getWeight();
558
}
559

    
560
/**
561
 * Order realms by default weight.
562
 */
563
function _variable_realm_sort_default($a, $b) {
564
  return $a->getDefaultWeight() - $b->getDefaultWeight();
565
}
566

    
567
/**
568
 * Order realms by current weight.
569
 */
570
function _variable_realm_sort_current($a, $b) {
571
  return $a->getWeight() - $b->getWeight();
572
}
573

    
574
/**
575
 * Get status (current key) for realm controller.
576
 */
577
function _variable_realm_status($realm_controller) {
578
  return $realm_controller->getKey();
579
}
580

    
581
/**
582
 * Invoke variable realm hook on all currently loaded modules.
583
 *
584
 * Variable realm usually starts from bootstrap, on hook_boot() and from here it is not
585
 * safe to user regular hook invokation so we use our own function, similar to
586
 * bootstrap_invoke_all() but returning the values (with deep merge).
587
 *
588
 * @see boostrap_invoke_all()
589
 * @see module_invoke()
590
 *
591
 * @pram $hook
592
 *   Hook to invoke in all loaded modules
593
 * @param $arg1, $arg2...
594
 *   A variable number of arguments.
595
 */
596
function _variable_realm_invoke_all() {
597
  $args = func_get_args();
598
  $hook = array_shift($args);
599
  $result = array();
600
  foreach (module_list() as $module) {
601
    if (module_hook($module, $hook) && $merge = call_user_func_array($module . '_' . $hook, $args)) {
602
      $result = drupal_array_merge_deep($result, $merge);
603
      // Add module name to each of the realms provided by the module.
604
      foreach (array_keys($merge) as $key) {
605
        $result[$key] += array('module' => $module);
606
      };
607
      unset($merge);
608
    }
609
  }
610
  return $result;
611
}
612

    
613
/**
614
 * Implements hook_form_FORM_ID_alter()
615
 */
616
function variable_realm_form_system_theme_settings_alter(&$form, &$form_state, $form_id) {
617
  form_load_include($form_state, 'form.inc', 'variable_realm');
618
  $theme_variable = $form['var']['#value'];
619
  foreach (_variable_realm_variable_settings_form_list() as $realm_name => $variables) {
620
    if (in_array($theme_variable, variable_children($variables))) {
621
      // Mark theme settings and include other variables in the form.
622
      _variable_realm_variable_settings_form_mark($realm_name, $form['theme_settings']);
623
      $realm_variables = element_children($form);
624
      $realm_variables = array_merge($realm_variables, array('default_logo', 'logo_path', 'default_favicon', 'favicon_path'));
625
      _variable_realm_variable_settings_form_alter($form, $realm_name, $realm_variables);
626
      // Replace variable (theme) name so we use a temporary storage variable
627
      $form['#realm_variables'][$realm_name] = $realm_variables;
628
      // This is a single variable so there can be one realm only.
629
      $form['#realm_theme'] = $realm_name;
630
      break;
631
    }
632
  }
633
  if (!empty($form['#realm_theme'])) {
634
    // Replace callback and user our own realm function.
635
    $form['#submit'] = str_replace('system_theme_settings_submit', 'variable_realm_variable_theme_form_submit', $form['#submit']);
636
    // Add realm switcher/s.
637
    _variable_realm_variable_settings_form_switcher($form);
638
  }
639
}