Projet

Général

Profil

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

root / drupal7 / sites / all / modules / ctools / includes / context-admin.inc @ 74f6bef0

1 85ad3d82 Assos Assos
<?php
2
3
/**
4
 * @file includes/common-context.inc
5
 * Provide API for adding contexts for modules that embed displays.
6
 *
7
 * Note that most of this code was directly copied from Panels 2, and as such
8
 * a lot of this code is crusty. It could probably stand to be rewritten,
9
 * and brought up to date, or at least better commented.
10
 */
11
12
/**
13
 * Provide a list of the ways contexts can be embedded.
14
 *
15
 * This provides a full list of context types that the tool understands
16
 * and can let modules utilize.
17
 */
18
function ctools_context_info($type = NULL) {
19
  static $info = NULL;
20
21
  // static doesn't work with functions like t().
22
  if (empty($info)) {
23
    $info = array(
24
      'argument' => array(
25
        'title' => t('Arguments'),
26
        'singular title' => t('argument'),
27
        'description' => '', // t("Arguments are parsed from the URL and translated into contexts that may be added to the display via the 'content' tab. These arguments are parsed in the order received, and you may use % in your URL to hold the place of an object; the rest of the arguments will come after the URL. For example, if the URL is node/%/panel and your user visits node/1/panel/foo, the first argument will be 1, and the second argument will be foo."),
28
        'add button' => t('Add argument'),
29
        'context function' => 'ctools_get_argument',
30
        'key' => 'arguments', // the key that data will be stored on an object, eg $panel_page
31
        'sortable' => TRUE,
32
        'settings' => 'argument_settings',
33
      ),
34
      'relationship' => array(
35
        'title' => t('Relationships'),
36
        'singular title' => t('relationship'),
37
        'description' => '', // t('Relationships are contexts that are created from already existing contexts; the add relationship button will only appear once there is another context available. Relationships can load objects based upon how they are related to each other; for example, the author of a node, or a taxonomy term attached to a node, or the vocabulary of a taxonomy term.'),
38
        'add button' => t('Add relationship'),
39
        'context function' => 'ctools_get_relationship',
40
        'key' => 'relationships',
41
        'sortable' => FALSE,
42
        'settings' => 'relationship_settings',
43
      ),
44
      'context' => array(
45
        'title' => t('Contexts'),
46
        'singular title' => t('context'),
47
        'description' => '', // t('Contexts are embedded directly into the panel; you generally must select an object in the panel. For example, you could select node 5, or the term "animals" or the user "administrator"'),
48
        'add button' => t('Add context'),
49
        'context function' => 'ctools_get_context',
50
        'key' => 'contexts',
51
        'sortable' => FALSE,
52
        'settings' => 'context_settings',
53
      ),
54
      'requiredcontext' => array(
55
        'title' => t('Required contexts'),
56
        'singular title' => t('required context'),
57
        'description' => '', // t('Required contexts are passed in from some external source, such as a containing panel. If a mini panel has required contexts, it can only appear when that context is available, and therefore will not show up as a standard Drupal block.'),
58
        'add button' => t('Add required context'),
59
        'context function' => 'ctools_get_context',
60
        'key' => 'requiredcontexts',
61
        'sortable' => FALSE,
62
      ),
63
    );
64
  }
65
66
  if ($type === NULL) {
67
    return $info;
68
  }
69
70
  return $info[$type];
71
}
72
73
74
/**
75
 * Get the data belonging to a particular context.
76
 */
77
function ctools_context_get_plugin($type, $name) {
78
  $info = ctools_context_info($type);
79
  if (function_exists($info['context function'])) {
80
    return $info['context function']($name);
81
  }
82
}
83
84
/**
85
 * Add the argument table plus gadget plus javascript to the form.
86
 */
87
function ctools_context_add_argument_form($module, &$form, &$form_state, &$form_location, $object, $cache_key = NULL) {
88
  if (empty($cache_key)) {
89
    $cache_key = $object->name;
90
  }
91
92
  $form_location = array(
93
    '#prefix' => '<div id="ctools-arguments-table">',
94
    '#suffix' => '</div>',
95
    '#theme' => 'ctools_context_item_form',
96
    '#cache_key' => $cache_key,
97
    '#ctools_context_type' => 'argument',
98
    '#ctools_context_module' => $module,
99
  );
100
101
  $args = ctools_get_arguments();
102
  $choices = array();
103
  foreach ($args as $name => $arg) {
104
    if (empty($arg['no ui'])) {
105
      $choices[$name] = $arg['title'];
106
    }
107
  }
108
109
  asort($choices);
110
111
  if (!empty($choices) || !empty($object->arguments)) {
112
    ctools_context_add_item_table('argument', $form_location, $choices, $object->arguments);
113
  }
114
}
115
116
function ctools_context_add_context_form($module, &$form, &$form_state, &$form_location, $object, $cache_key = NULL) {
117
  if (empty($cache_key)) {
118
    $cache_key = $object->name;
119
  }
120
121
  $form_location = array(
122
    '#prefix' => '<div id="ctools-contexts-table">',
123
    '#suffix' => '</div>',
124
    '#theme' => 'ctools_context_item_form',
125
    '#cache_key' => $cache_key,
126
    '#ctools_context_type' => 'context',
127
    '#ctools_context_module' => $module,
128
  );
129
130
  // Store the order the choices are in so javascript can manipulate it.
131
  $form_location['markup'] = array(
132
    '#markup' => '&nbsp;',
133
  );
134
135
  $choices = array();
136
  foreach (ctools_get_contexts() as $name => $arg) {
137
    if (empty($arg['no ui'])) {
138
      $choices[$name] = $arg['title'];
139
    }
140
  }
141
142
  asort($choices);
143
144
  if (!empty($choices) || !empty($object->contexts)) {
145
    ctools_context_add_item_table('context', $form_location, $choices, $object->contexts);
146
  }
147
148
}
149
150
function ctools_context_add_required_context_form($module, &$form, &$form_state, &$form_location, $object, $cache_key = NULL) {
151
  if (empty($cache_key)) {
152
    $cache_key = $object->name;
153
  }
154
155
  $form_location = array(
156
    '#prefix' => '<div id="ctools-requiredcontexts-table">',
157
    '#suffix' => '</div>',
158
    '#theme' => 'ctools_context_item_form',
159
    '#cache_key' => $cache_key,
160
    '#ctools_context_type' => 'requiredcontext',
161
    '#ctools_context_module' => $module,
162
  );
163
164
  // Store the order the choices are in so javascript can manipulate it.
165
  $form_location['markup'] = array(
166
    '#value' => '&nbsp;',
167
  );
168
169
  $choices = array();
170
  foreach (ctools_get_contexts() as $name => $arg) {
171
    if (empty($arg['no required context ui'])) {
172
      $choices[$name] = $arg['title'];
173
    }
174
  }
175
176
  asort($choices);
177
178
  if (!empty($choices) || !empty($object->contexts)) {
179
    ctools_context_add_item_table('requiredcontext', $form_location, $choices, $object->requiredcontexts);
180
  }
181
}
182
183
function ctools_context_add_relationship_form($module, &$form, &$form_state, &$form_location, $object, $cache_key = NULL) {
184
  if (empty($cache_key)) {
185
    $cache_key = $object->name;
186
  }
187
188
  $form_location = array(
189
    '#prefix' => '<div id="ctools-relationships-table">',
190
    '#suffix' => '</div>',
191
    '#theme' => 'ctools_context_item_form',
192
    '#cache_key' => $cache_key,
193
    '#ctools_context_type' => 'relationship',
194
    '#ctools_context_module' => $module,
195
  );
196
197
  // Store the order the choices are in so javascript can manipulate it.
198
  $form_location['markup'] = array(
199
    '#value' => '&nbsp;',
200
  );
201
202
  $base_contexts = isset($object->base_contexts) ? $object->base_contexts : array();
203
  $available_relationships = ctools_context_get_relevant_relationships(ctools_context_load_contexts($object, TRUE, $base_contexts));
204
205
  ctools_context_add_item_table('relationship', $form_location, $available_relationships, $object->relationships);
206
}
207
208
/**
209
 * Include all context administrative include files, css, javascript.
210
 */
211
function ctools_context_admin_includes() {
212
  ctools_include('context');
213
  ctools_include('modal');
214
  ctools_include('ajax');
215
  ctools_include('object-cache');
216
  ctools_modal_add_js();
217
  ctools_modal_add_plugin_js(ctools_get_contexts());
218
  ctools_modal_add_plugin_js(ctools_get_relationships());
219
}
220
221
/**
222
 * Add the context table to the page.
223
 */
224
function ctools_context_add_item_table($type, &$form, $available_contexts, $items) {
225
  $form[$type] = array(
226
    '#tree' => TRUE,
227
  );
228
229
  $module = $form['#ctools_context_module'];
230
  $cache_key   = $form['#cache_key'];
231
232
  if (isset($items) && is_array($items)) {
233
    foreach ($items as $position => $context) {
234
      ctools_context_add_item_to_form($module, $type, $cache_key, $form[$type][$position], $position, $context);
235
    }
236
  }
237
238
  $type_info = ctools_context_info($type);
239
  $form['description'] = array(
240
    '#prefix' => '<div class="description">',
241
    '#suffix' => '</div>',
242
    '#markup' => $type_info['description'],
243
  );
244
245
  ctools_context_add_item_table_buttons($type, $module, $form, $available_contexts);
246
}
247
248
function ctools_context_add_item_table_buttons($type, $module, &$form, $available_contexts) {
249
  drupal_add_library('system', 'drupal.ajax');
250
  $form['buttons'] = array(
251
    '#tree' => TRUE,
252
  );
253
254
  if (!empty($available_contexts)) {
255
    $type_info = ctools_context_info($type);
256
257
    $module = $form['#ctools_context_module'];
258
    $cache_key   = $form['#cache_key'];
259
260
    // The URL for this ajax button
261
    $form['buttons'][$type]['add-url'] = array(
262
      '#attributes' => array('class' => array("ctools-$type-add-url")),
263
      '#type' => 'hidden',
264
      '#value' => url("ctools/context/ajax/add/$module/$type/$cache_key", array('absolute' => TRUE)),
265
    );
266
267
    asort($available_contexts);
268
    // This also will be in the URL.
269
    $form['buttons'][$type]['item'] = array(
270
      '#attributes' => array('class' => array("ctools-$type-add-url")),
271
      '#type' => 'select',
272
      '#options' => $available_contexts,
273
      '#required' => FALSE,
274
    );
275
276
    $form['buttons'][$type]['add'] = array(
277
      '#type' => 'submit',
278
      '#attributes' => array('class' => array('ctools-use-modal')),
279
      '#id' => "ctools-$type-add",
280
      '#value' => $type_info['add button'],
281
    );
282
  }
283
}
284
285
/**
286
 * Add a row to the form. Used both in the main form and by
287
 * the ajax to add an item.
288
 */
289
function ctools_context_add_item_to_form($module, $type, $cache_key, &$form, $position, $item) {
290
  // This is the single function way to load any plugin by variable type.
291
  $info = ctools_context_get_plugin($type, $item['name']);
292
  $form['title'] = array(
293
    '#markup' => check_plain($item['identifier']),
294
  );
295
296
  // Relationships not sortable.
297
  $type_info = ctools_context_info($type);
298
299
  if (!empty($type_info['sortable'])) {
300
    $form['position'] = array(
301
      '#type' => 'weight',
302
      '#default_value' => $position,
303
      '#attributes' => array('class' => array('drag-position')),
304
    );
305
  }
306
307
  $form['remove'] = array(
308
    '#markup' => ctools_ajax_image_button(ctools_image_path('icon-delete.png'), "ctools/context/ajax/delete/$module/$type/$cache_key/$position", t('Remove this item.')),
309
  );
310
311
  $form['settings'] = array(
312
    '#markup' => ctools_modal_image_button(ctools_image_path('icon-configure.png'), "ctools/context/ajax/configure/$module/$type/$cache_key/$position", t('Configure settings for this item.')),
313
  );
314
}
315
316
317
// ---------------------------------------------------------------------------
318
// AJAX forms and stuff.
319
320
/**
321
 * Ajax entry point to add an context
322
 */
323
function ctools_context_ajax_item_add($mechanism = NULL, $type = NULL, $cache_key = NULL, $name = NULL, $step = NULL) {
324
  ctools_include('ajax');
325
  ctools_include('modal');
326
  ctools_include('context');
327
  ctools_include('cache');
328
  ctools_include('plugins-admin');
329
330
  if (!$name) {
331
    return ctools_ajax_render_error();
332
  }
333
334
  // Load stored object from cache.
335
  if (!($object = ctools_cache_get($mechanism, $cache_key))) {
336
    ctools_ajax_render_error(t('Invalid object name.'));
337
  }
338
339
  // Get info about what we're adding, i.e, relationship, context, argument, etc.
340
  $plugin_definition = ctools_context_get_plugin($type, $name);
341
  if (empty($plugin_definition)) {
342
    ctools_ajax_render_error(t('Invalid context type'));
343
  }
344
345
  // Set up the $conf array for this plugin
346
  if (empty($step) || empty($object->temporary)) {
347
    // Create the basis for our new context.
348
    $conf = ctools_context_get_defaults($plugin_definition, $object, $type);
349
    $object->temporary = &$conf;
350
  }
351
  else {
352
    $conf = &$object->temporary;
353
  }
354
355
  // Load the contexts that may be used.
356
  $base_contexts = isset($object->base_contexts) ? $object->base_contexts : array();
357
  $contexts = ctools_context_load_contexts($object, TRUE, $base_contexts);
358
359
  $type_info = ctools_context_info($type);
360
  $form_state = array(
361
    'ajax' => TRUE,
362
    'modal' => TRUE,
363
    'modal return' => TRUE,
364
    'object' => &$object,
365
    'conf' => &$conf,
366
    'plugin' => $plugin_definition,
367
    'type' => $type,
368
    'contexts' => $contexts,
369
    'title' => t('Add @type "@context"', array('@type' => $type_info['singular title'], '@context' => $plugin_definition['title'])),
370
    'type info' => $type_info,
371
    'op' => 'add',
372
    'step' => $step,
373
  );
374
375
  $form_info = array(
376
    'path' => "ctools/context/ajax/add/$mechanism/$type/$cache_key/$name/%step",
377
    'show cancel' => TRUE,
378
    'default form' => 'ctools_edit_context_form_defaults',
379
    'auto caching' => TRUE,
380
    'cache mechanism' => $mechanism,
381
    'cache key' => $cache_key,
382
    // This is stating what the cache will be referred to in $form_state
383
    'cache storage' => 'object',
384
  );
385
386
  if ($type == 'requiredcontext') {
387
    $form_info += array(
388
      'add form name' => 'required context add form',
389
      'edit form name' => 'required context edit form',
390
    );
391
  }
392
393
  $output = ctools_plugin_configure_form($form_info, $form_state);
394
395
  if (!empty($form_state['cancel'])) {
396
    $output = array(ctools_modal_command_dismiss());
397
  }
398
  else if (!empty($form_state['complete'])) {
399
    // Successful submit -- move temporary data to location.
400
401
    // Create a reference to the place our context lives. Since this is fairly
402
    // generic, this is the easiest way to get right to the place of the
403
    // object without knowing precisely what data we're poking at.
404
    $ref = &$object->{$type_info['key']};
405
406
    // Figure out the position for our new context.
407
    $position = empty($ref) ? 0 : max(array_keys($ref)) + 1;
408
409
    $conf['id'] = ctools_context_next_id($ref, $name);
410
    $ref[$position] = $conf;
411
412
    if (isset($object->temporary)) {
413
      unset($object->temporary);
414
    }
415
416
    ctools_cache_operation($mechanism, $cache_key, 'finalize', $object);
417
418
    // Very irritating way to update the form for our contexts.
419 3753f249 Assos Assos
    $arg_form_state = array(
420
      'values' => array(),
421
      'programmed' => FALSE,
422
      'process_input' => FALSE,
423
      'complete form' => array(),
424
    );
425 85ad3d82 Assos Assos
426
    $arg_form = array(
427
      '#post' => array(),
428
      '#programmed' => FALSE,
429
      '#tree' => FALSE,
430 3753f249 Assos Assos
      '#parents' => array(),
431
      '#array_parents' => array(),
432 85ad3d82 Assos Assos
    );
433
434
    // Build a chunk of the form to merge into the displayed form
435
    $arg_form[$type] = array(
436
      '#tree' => TRUE,
437
    );
438
    $arg_form[$type][$position] = array(
439
      '#tree' => TRUE,
440
    );
441
442
    ctools_context_add_item_to_form($mechanism, $type, $cache_key, $arg_form[$type][$position], $position, $ref[$position]);
443
    $arg_form = form_builder('ctools_context_form', $arg_form, $arg_form_state);
444
445
    // Build the relationships table so we can ajax it in.
446
    // This is an additional thing that goes in here.
447
    $rel_form = array(
448
      '#theme' => 'ctools_context_item_form',
449
      '#cache_key' => $cache_key,
450
      '#ctools_context_type' => 'relationship',
451
      '#ctools_context_module' => $mechanism,
452
      '#only_buttons' => TRUE,
453
      '#post' => array(),
454
      '#programmed' => FALSE,
455
      '#tree' => FALSE,
456 3753f249 Assos Assos
      '#parents' => array(),
457
      '#array_parents' => array(),
458 85ad3d82 Assos Assos
    );
459
460
    $rel_form['relationship'] = array(
461
      '#tree' => TRUE,
462
    );
463
464
    // Allow an object to set some 'base' contexts that come from elsewhere.
465
    $rel_contexts = isset($object->base_contexts) ? $object->base_contexts : array();
466
    $all_contexts = ctools_context_load_contexts($object, TRUE, $rel_contexts);
467
    $available_relationships = ctools_context_get_relevant_relationships($all_contexts);
468
469
    $output = array();
470
    if (!empty($available_relationships)) {
471
      ctools_context_add_item_table_buttons('relationship', $mechanism, $rel_form, $available_relationships);
472
      $rel_form = form_builder('dummy_form_id', $rel_form, $arg_form_state);
473
      $output[] = ajax_command_replace('div#ctools-relationships-table div.buttons', drupal_render($rel_form));
474
    }
475
476
    $theme_vars = array();
477
    $theme_vars['type'] = $type;
478
    $theme_vars['form'] = $arg_form[$type][$position];
479
    $theme_vars['position'] = $position;
480
    $theme_vars['count'] = $position;
481
    $text = theme('ctools_context_item_row', $theme_vars);
482
    $output[] = ajax_command_append('#' . $type . '-table tbody', $text);
483
    $output[] = ajax_command_changed('#' . $type . '-row-' . $position, '.title');
484
    $output[] = ctools_modal_command_dismiss();
485
  }
486
  else {
487
    $output = ctools_modal_form_render($form_state, $output);
488
  }
489
  print ajax_render($output);
490
  exit;
491
}
492
493
/**
494
 * Ajax entry point to edit an item
495
 */
496
function ctools_context_ajax_item_edit($mechanism = NULL, $type = NULL, $cache_key = NULL, $position = NULL, $step = NULL) {
497
  ctools_include('ajax');
498
  ctools_include('modal');
499
  ctools_include('context');
500
  ctools_include('cache');
501
  ctools_include('plugins-admin');
502
503
  if (!isset($position)) {
504
    return ctools_ajax_render_error();
505
  }
506
507
  // Load stored object from cache.
508
  if (!($object = ctools_cache_get($mechanism, $cache_key))) {
509
    ctools_ajax_render_error(t('Invalid object name.'));
510
  }
511
512
  $type_info = ctools_context_info($type);
513
514
  // Create a reference to the place our context lives. Since this is fairly
515
  // generic, this is the easiest way to get right to the place of the
516
  // object without knowing precisely what data we're poking at.
517
  $ref = &$object->{$type_info['key']};
518
519
  if (empty($step) || empty($object->temporary)) {
520
    // Create the basis for our new context.
521
    $conf = $object->{$type_info['key']}[$position];
522
    $object->temporary = &$conf;
523
  }
524
  else {
525
    $conf = &$object->temporary;
526
  }
527
528
  $name = $ref[$position]['name'];
529
  if (empty($name)) {
530
    ctools_ajax_render_error();
531
  }
532
533
  // load the plugin definition
534
  $plugin_definition = ctools_context_get_plugin($type, $name);
535
  if (empty($plugin_definition)) {
536
    ctools_ajax_render_error(t('Invalid context type'));
537
  }
538
539
  // Load the contexts
540
  $base_contexts = isset($object->base_contexts) ? $object->base_contexts : array();
541
  $contexts = ctools_context_load_contexts($object, TRUE, $base_contexts);
542
543
  $form_state = array(
544
    'ajax' => TRUE,
545
    'modal' => TRUE,
546
    'modal return' => TRUE,
547
    'object' => &$object,
548
    'conf' => &$conf,
549
    'position' => $position,
550
    'plugin' => $plugin_definition,
551
    'type' => $type,
552
    'contexts' => $contexts,
553
    'title' => t('Edit @type "@context"', array('@type' => $type_info['singular title'], '@context' => $plugin_definition['title'])),
554
    'type info' => $type_info,
555
    'op' => 'add',
556
    'step' => $step,
557
  );
558
559
  $form_info = array(
560
    'path' => "ctools/context/ajax/configure/$mechanism/$type/$cache_key/$position/%step",
561
    'show cancel' => TRUE,
562
    'default form' => 'ctools_edit_context_form_defaults',
563
    'auto caching' => TRUE,
564
    'cache mechanism' => $mechanism,
565
    'cache key' => $cache_key,
566
    // This is stating what the cache will be referred to in $form_state
567
    'cache storage' => 'object',
568
  );
569
570
  if ($type == 'requiredcontext') {
571
    $form_info += array(
572
      'add form name' => 'required context add form',
573
      'edit form name' => 'required context edit form',
574
    );
575
  }
576
577
  $output = ctools_plugin_configure_form($form_info, $form_state);
578
579
  if (!empty($form_state['cancel'])) {
580
    $output = array(ctools_modal_command_dismiss());
581
  }
582
  else if (!empty($form_state['complete'])) {
583
    // successful submit
584
    $ref[$position] = $conf;
585
    if (isset($object->temporary)) {
586
      unset($object->temporary);
587
    }
588
589
    ctools_cache_operation($mechanism, $cache_key, 'finalize', $object);
590
591
    $output = array();
592
    $output[] = ctools_modal_command_dismiss();
593
594
    $arg_form = array(
595
      '#post' => array(),
596
      '#programmed' => FALSE,
597
      '#tree' => FALSE,
598
    );
599
600
    // Build a chunk of the form to merge into the displayed form
601
    $arg_form[$type] = array(
602
      '#tree' => TRUE,
603
    );
604
    $arg_form[$type][$position] = array(
605
      '#tree' => TRUE,
606
    );
607
608
    ctools_context_add_item_to_form($mechanism, $type, $cache_key, $arg_form[$type][$position], $position, $ref[$position]);
609
    $arg_form = form_builder('ctools_context_form', $arg_form, $arg_form_state);
610
611
    $theme_vars = array();
612
    $theme_vars['type'] = $type;
613
    $theme_vars['form'] = $arg_form[$type][$position];
614
    $theme_vars['position'] = $position;
615
    $theme_vars['count'] = $position;
616
    $output[] = ajax_command_replace('#' . $type . '-row-' . $position, theme('ctools_context_item_row', $theme_vars));
617
    $output[] = ajax_command_changed('#' . $type . '-row-' . $position, '.title');
618
  }
619
  else {
620
    $output = ctools_modal_form_render($form_state, $output);
621
  }
622
  print ajax_render($output);
623
  exit;
624
}
625
626
/**
627
 * Get the defaults for a new instance of a context plugin.
628
 *
629
 * @param $plugin_definition
630
 *   The metadata definition of the plugin from ctools_get_plugins().
631
 * @param $object
632
 *   The object the context plugin will be added to.
633
 * @param $type
634
 *   The type of context plugin. i.e, context, requiredcontext, relationship
635
 */
636
function ctools_context_get_defaults($plugin_definition, $object, $type) {
637
  // Fetch the potential id of the plugin so we can append
638
  // title and keyword information for new ones.
639
  $type_info = ctools_context_info($type);
640
  $id = ctools_context_next_id($object->{$type_info['key']}, $plugin_definition['name']);
641
642
  $conf = array(
643
    'identifier' => $plugin_definition['title'] . ($id > 1 ? ' ' . $id : ''),
644
    'keyword' => ctools_get_keyword($object, $plugin_definition['keyword']),
645
    'name' => $plugin_definition['name'],
646
  );
647
648
  if (isset($plugin_definition['defaults'])) {
649
    $defaults = $plugin_definition['defaults'];
650
  }
651
  else if (isset($subtype['defaults'])) {
652
    $defaults = $subtype['defaults'];
653
  }
654
655
  if (isset($defaults)) {
656
    if (is_string($defaults) && function_exists($defaults)) {
657
      if ($settings = $defaults($plugin_definition)) {
658
        $conf += $settings;
659
      }
660
    }
661
    else if (is_array($defaults)) {
662
      $conf += $defaults;
663
    }
664
  }
665
666
  return $conf;
667
}
668
669
/**
670
 * Form wrapper for the edit context form.
671
 *
672
 * @todo: We should uncombine these.
673
 */
674
function ctools_edit_context_form_defaults($form, &$form_state) {
675
  // Basic values required to orient ourselves
676
  $object            = $form_state['object'];
677
  $plugin_definition = $form_state['plugin'];
678
  $type_info         = $form_state['type info'];
679
  $contexts          = $form_state['contexts'];
680
  $conf             = $form_state['conf'];
681
682
  if ($type_info['key'] == 'arguments' && !isset($conf['default'])) {
683
    $conf['default'] = 'ignore';
684
    $conf['title'] = '';
685
  }
686
687
  $form['description'] = array(
688
    '#prefix' => '<div class="description">',
689
    '#suffix' => '</div>',
690
    '#markup' => check_plain($plugin_definition['description']),
691
  );
692
693
  if ($type_info['key'] == 'relationships') {
694
    $form['context'] = ctools_context_selector($contexts, $plugin_definition['required context'], isset($conf['context']) ? $conf['context'] : '');
695
  }
696
  if ($type_info['key'] == 'arguments') {
697
    $form['default'] = array(
698
      '#type' => 'select',
699
      '#title' => t('Default'),
700
      '#options' => array(
701
        'ignore' => t('Ignore it; content that requires this context will not be available.'),
702
        '404' => t('Display page not found or display nothing at all.'),
703
      ),
704
      '#default_value' => $conf['default'],
705
      '#description' => t('If the argument is missing or is not valid, select how this should behave.'),
706
    );
707
708
    $form['title'] = array(
709
      '#type' => 'textfield',
710
      '#title' => t('Title'),
711
      '#default_value' => $conf['title'],
712
      '#description' => t('Enter a title to use when this argument is present. You may use %KEYWORD substitution, where the keyword is specified below.'),
713
    );
714
  }
715
716
  $form['identifier'] = array(
717
    '#type' => 'textfield',
718
    '#title' => t('Identifier'),
719
    '#description' => t('Enter a name to identify this !type on administrative screens.', array('!type' => t('context'))),
720
    '#default_value' => $conf['identifier'],
721
  );
722
723
  $form['keyword'] = array(
724
    '#type' => 'textfield',
725
    '#title' => t('Keyword'),
726
    '#description' => t('Enter a keyword to use for substitution in titles.'),
727
    '#default_value' => $conf['keyword'],
728
  );
729
730
  $form['#submit'][] = 'ctools_edit_context_form_defaults_submit';
731
732
  return $form;
733
}
734
735
/**
736
 * Submit handler to store context identifier and keyword info.
737
 */
738
function ctools_edit_context_form_defaults_submit(&$form, &$form_state) {
739
  if ($form_state['type info']['key'] == 'relationships') {
740
    $form_state['conf']['context'] = $form_state['values']['context'];
741
  }
742
  if ($form_state['type info']['key'] == 'arguments') {
743
    $form_state['conf']['default'] = $form_state['values']['default'];
744
    $form_state['conf']['title'] = $form_state['values']['title'];
745
  }
746
747
  $form_state['conf']['identifier'] = $form_state['values']['identifier'];
748
  $form_state['conf']['keyword'] = $form_state['values']['keyword'];
749
}
750
751
/**
752
 * Ajax entry point to edit an item
753
 */
754
function ctools_context_ajax_item_delete($mechanism = NULL, $type = NULL, $cache_key = NULL, $position = NULL) {
755
  ctools_include('ajax');
756
  ctools_include('context');
757
  ctools_include('cache');
758
759
  if (!isset($position)) {
760
    return ctools_ajax_render_error();
761
  }
762
763
  // Load stored object from cache.
764
  if (!($object = ctools_cache_get($mechanism, $cache_key))) {
765
    ctools_ajax_render_error(t('Invalid object name.'));
766
  }
767
768
  $type_info = ctools_context_info($type);
769
770
  // Create a reference to the place our context lives. Since this is fairly
771
  // generic, this is the easiest way to get right to the place of the
772
  // object without knowing precisely what data we're poking at.
773
  $ref = &$object->{$type_info['key']};
774
775
  if (!array_key_exists($position, $ref)) {
776
    ctools_ajax_render_error(t('Unable to delete missing item!'));
777
  }
778
779
  unset($ref[$position]);
780
  ctools_cache_operation($mechanism, $cache_key, 'finalize', $object);
781
782
  $output   = array();
783
  $output[] = ajax_command_replace('#' . $type . '-row-' . $position, '');
784
  $output[] = ajax_command_restripe("#$type-table");
785
  print ajax_render($output);
786
  exit;
787
}
788
789
// --- End of contexts
790
791
function ctools_save_context($type, &$ref, $form_values) {
792
  $type_info = ctools_context_info($type);
793
794
  // Organize arguments
795
  $new = array();
796
  $order = array();
797
798
  foreach ($ref as $id => $context) {
799
    $position = $form_values[$type][$id]['position'];
800
    $order[$position] = $id;
801
  }
802
803
  ksort($order);
804
  foreach ($order as $id) {
805
    $new[] = $ref[$id];
806
  }
807
  $ref = $new;
808
}
809
810
function ctools_get_keyword($page, $word) {
811
  // Create a complete set of keywords
812
  $keywords = array();
813
  foreach (array('arguments', 'relationships', 'contexts', 'requiredcontexts') as $type) {
814
    if (!empty($page->$type) && is_array($page->$type)) {
815
      foreach ($page->$type as $info) {
816
        $keywords[$info['keyword']] = TRUE;
817
      }
818
    }
819
  }
820
821
  $keyword = $word;
822
  $count = 1;
823
  while (!empty($keywords[$keyword])) {
824
    $keyword = $word . '_' . ++$count;
825
  }
826
  return $keyword;
827
}