Projet

Général

Profil

Paste
Télécharger (23,5 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / panels / includes / common.inc @ 73ab1d0a

1 85ad3d82 Assos Assos
<?php
2
3
4
/**
5
 * @file
6
 * Functions used by more than one panels client module.
7
 */
8
9
/**
10
 * Class definition for the allowed layouts governing structure.
11
 *
12
 * @ingroup mainapi
13
 *
14
 * This class is designed to handle panels allowed layouts data from start to finish, and sees
15
 * action at two times:\n
16
 *    - When a client module wants to generate a form allowing an admin to create or edit a set
17
 *      of allowed layouts. In this case, either a new panels_allowed_layouts object is created
18
 *      or one is retrieved from storage and panels_allowed_layouts::set_allowed() is called to
19
 *      generate the allowed layouts form. \n
20
 *    - When a client module is calling panels_edit_layout(), a saved instantiation of this object
21
 *      can be called up and passed in to the fourth parameter, and only the allowed layouts saved
22
 *      in that object will be displayed on the form. \n
23
 * Because the panels API does not impose a data structure on the allowed_layouts data, client
24
 * modules can create as many of these objects as they want, and organize them around any concept:
25
 * node types, date published, author roles...anything.
26
 *
27
 * To call the settings form, instantiate this class - or, if your client module's needs are
28
 * heavy-duty, extend this class and instantiate your subclass - assign values to any relevant
29
 * desired members, and call panels_allowed_layouts::set_allowed(). See the documentation on
30
 * that method for a sample implementation.
31
 *
32
 * Note that when unserializing saved tokens of this class, you must
33
 * run panels_load_include('common') before unserializing in order to ensure
34
 * that the object is properly loaded.
35
 *
36
 * Client modules extending this class should implement a save() method and use it for
37
 * their custom data storage routine. You'll need to rewrite other class methods if
38
 * you choose to go another route.
39
 *
40
 * @see panels_edit_layout()
41
 * @see _panels_edit_layout()
42
 */
43
class panels_allowed_layouts {
44
45
  /**
46 64156087 Assos Assos
   * Specifies whether newly-added layouts (as in, new .inc files) should be automatically
47 85ad3d82 Assos Assos
   *  allowed (TRUE) or disallowed (FALSE) for $this. Defaults to TRUE, which is more
48
   *  permissive but less of an administrative hassle if/when you add new layouts. Note
49
   *  that this parameter will be derived from $allowed_layouts if a value is passed in.
50
   */
51
  var $allow_new = TRUE;
52
53
  /**
54 64156087 Assos Assos
   * Optional member. If provided, the Panels API will generate a drupal variable using
55 85ad3d82 Assos Assos
   *  variable_set($module_name . 'allowed_layouts', serialize($this)), thereby handling the
56
   *  storage of this object entirely within the Panels API. This object will be
57
   *  called and rebuilt by panels_edit_layout() if the same $module_name string is passed in
58
   *  for the $allowed_types parameter. \n
59
   *  This is primarily intended for convenience - client modules doing heavy-duty implementations
60
   *  of the Panels API will probably want to create their own storage method.
61 64156087 Assos Assos
   *
62 85ad3d82 Assos Assos
   * @see panels_edit_layout()
63
   */
64
  var $module_name = NULL;
65
66
  /**
67 64156087 Assos Assos
   * An associative array of all available layouts, keyed by layout name (as defined
68 85ad3d82 Assos Assos
   *  in the corresponding layout plugin definition), with value = 1 if the layout is
69
   *  allowed, and value = 0 if the layout is not allowed.
70
   *  Calling array_filter(panels_allowed_layouts::$allowed_layout_settings) will return an associative array
71
   *  containing only the allowed layouts, and wrapping that in array_keys() will
72
   *  return an indexed version of that array.
73
   */
74
  var $allowed_layout_settings = array();
75
76
  /**
77
   * Hack-imitation of D6's $form_state. Used by the panels_common_set_allowed_types()
78
   * form to indicate whether the returned value is in its 'render', 'failed-validate',
79
   * or 'submit' stage.
80
   */
81
  var $form_state;
82
83
  /**
84
   * Constructor function; loads the $allowed_layout_settings array with initial values according
85 64156087 Assos Assos
   * to $start_allowed.
86 85ad3d82 Assos Assos
   *
87
   * @param bool $start_allowed
88 64156087 Assos Assos
   *   $start_allowed determines whether all available layouts will be marked
89
   *   as allowed or not allowed on the initial call to panels_allowed_layouts::set_allowed()
90 85ad3d82 Assos Assos
   */
91 136a805a Assos Assos
  function __construct($start_allowed = TRUE) {
92 64156087 Assos Assos
    // TODO would be nice if there was a way to just fetch the names easily.
93 85ad3d82 Assos Assos
    foreach ($this->list_layouts() as $layout_name) {
94
      $this->allowed_layout_settings[$layout_name] = $start_allowed ? 1 : 0;
95
    }
96
  }
97
98
  /**
99
   * Manage panels_common_set_allowed_layouts(), the FAPI code for selecting allowed layouts.
100
   *
101
   * MAKE SURE to set panels_allowed_layouts::allow_new before calling this method. If you want the panels API
102
   * to handle saving these allowed layout settings, panels_allowed_layouts::module_name must also be set.
103
   *
104
   * Below is a sample implementation; refer to the rest of the class documentation to understand all the
105
   * specific pieces. Values that are intended to be replaced are wrapped with <>.
106
   *
107
   * \n @code
108
   *  function docdemo_allowed_layouts() {
109
   *    ctools_include('common', 'panels');
110
   *    if (!is_a($allowed_layouts = unserialize(variable_get('panels_common_allowed_layouts', serialize(''))), 'panels_allowed_layouts')) {
111
   *     $allowed_layouts = new panels_allowed_layouts();
112
   *      $allowed_layouts->allow_new = TRUE;
113
   *      $allowed_layouts->module_name = '<client_module_name>';
114
   *    }
115
   *    $result = $allowed_layouts->set_allowed('<Desired client module form title>');
116
   *    if (in_array($allowed_layouts->form_state, array('failed-validate', 'render'))) {
117
   *     return $result;
118
   *    }
119
   *    elseif ($allowed_layouts->form_state == 'submit') {
120
   *      drupal_goto('</path/to/desired/redirect>');
121
   *    }
122
   *  }
123 64156087 Assos Assos
   *
124 85ad3d82 Assos Assos
   * @endcode \n
125
   *
126
   * If $allowed_layouts->form_state == 'failed-validate' || 'render', then you'll need to return
127
   * $result as it contains the structured form HTML generated by drupal_render_form() and is ready
128
   * to be passed through index.php's call to theme('page', ...).
129
   *
130
   * However, if $allowed_layouts->form_state == 'submit', then the form has been submitted and we should
131
   * react. It's really up to your client module how you handle the rest; panels_allowed_layouts::save() (or
132
   * panels_allowed_layouts::api_save(), if that's the route you're going) will have already been called,
133
   * so if those methods handle your save routine, then all there is left to do is handle redirects, if you
134
   * want. The current implementation of the allowed layouts form currently never redirects, so it's up to
135
   * you to control where the user ends up next.
136
   *
137
   * @param string $title
138 64156087 Assos Assos
   *   Used to set the title of the allowed layouts form. If no value is given, defaults to
139
   *   'Panels: Allowed Layouts'.
140 85ad3d82 Assos Assos
   *
141
   * @return mixed $result
142
   *  - On the first passthrough when the form is being rendered, $result is the form's structured
143
   *    HTML, ready to be pushed to the screen with a call to theme('page', ...).
144
   *  - A successful second passthrough indicates a successful submit, and
145
   *    $result === panels_allowed_layouts::allowed_layout_settings. Returning it is simply for convenience.
146
   */
147
  function set_allowed($title = 'Panels: Allowed Layouts') {
148
    $this->sync_with_available();
149
    $form_id = 'panels_common_set_allowed_layouts';
150 64156087 Assos Assos
    // TODO switch to drupal_build_form(); need to pass by ref.
151 85ad3d82 Assos Assos
    $form = drupal_retrieve_form($form_id, $this, $title);
152
153
    if ($result = drupal_process_form($form_id, $form)) {
154 64156087 Assos Assos
      // Successful submit.
155 85ad3d82 Assos Assos
      $this->form_state = 'submit';
156
      return $result;
157
    }
158
    $this->form_state = isset($_POST['op']) ? 'failed-validate' : 'render';
159
    $result = drupal_render_form($form_id, $form);
160
    return $result;
161
  }
162
163
  /**
164
   * Checks for newly-added layouts and deleted layouts. If any are found, updates panels_allowed_layouts::allowed_layout_settings;
165
   * new additions are made according to panels_allowed_layouts::allow_new, while deletions are unset().
166
   *
167
   * Note that any changes made by this function are not saved in any permanent location.
168
   */
169
  function sync_with_available() {
170
    $layouts = $this->list_layouts();
171
    foreach (array_diff($layouts, array_keys($this->allowed_layout_settings)) as $new_layout) {
172
      $this->allowed_layout_settings[$new_layout] = $this->allow_new ? 1 : 0;
173
    }
174
    foreach (array_diff(array_keys($this->allowed_layout_settings), $layouts) as $deleted_layout) {
175
      unset($this->allowed_layout_settings[$deleted_layout]);
176
    }
177
  }
178
179
  /**
180
   * Use panels_allowed_layouts::module_name to generate a variable for variable_set(), in which
181
   * a serialized version of $this will be stored.
182
   *
183
   * Does nothing if panels_allowed_layouts::module_name is not set.
184
   *
185
   * IMPORTANT NOTE: if you use variable_get() in a custom client module save() method, you MUST
186
   * wrap $this in serialize(), then unserialize() what you get from variable_get(). Failure to
187
   * do so will result in an incomplete object. The following code will work:
188
   * @code
189
   *  $allowed_layouts = unserialize(variable_get('your_variable_name', serialize(''));
190
   * @endcode
191
   *
192
   * If you don't serialize the second parameter of variable_get() and the variable name you provide
193
   * can't be found, an E_STRICT warning will be generated for trying to unserialize an entity
194
   * that has not been serialized.
195
   */
196
  function save() {
197
    if (!is_null($this->module_name)) {
198 64156087 Assos Assos
      variable_set($this->module_name . "_allowed_layouts", serialize($this));
199 85ad3d82 Assos Assos
    }
200
  }
201
202
  /**
203
   * Snag a list of the current layouts for internal use.
204
   *
205
   * Data is not saved in a class member in order to ensure that it's
206
   * fresh.
207
   *
208
   * @return array $layouts
209
   *  An indexed array of the system names for all currently available layouts.
210
   */
211
  function list_layouts() {
212
    static $layouts = array();
213
    if (empty($layouts)) {
214
      ctools_include('plugins', 'panels');
215
      $layouts = array_keys(panels_get_layouts());
216
    }
217
    return $layouts;
218
  }
219 64156087 Assos Assos
220 85ad3d82 Assos Assos
}
221
222
/**
223
 * A common settings page for Panels modules, because this code is relevant to
224
 * any modules that don't already have special requirements.
225
 */
226
function panels_common_settings($form, &$form_state, $module_name = 'panels_common') {
227
  ctools_include('plugins', 'panels');
228
  ctools_include('content');
229
  $content_types = ctools_get_content_types();
230
  $skip = FALSE;
231
232
  $default_types = variable_get($module_name . '_default', NULL);
233
  if (!isset($default_types)) {
234
    $default_types = array('other' => TRUE);
235
    $skip = TRUE;
236
  }
237
238
  foreach ($content_types as $id => $info) {
239
    if (empty($info['single'])) {
240
      $default_options[$id] = t('New @s', array('@s' => $info['title']));
241
      if ($skip) {
242
        $default_types[$id] = TRUE;
243
      }
244
    }
245
  }
246
247
  $default_options['other'] = t('New content of other types');
248
249
  $form['additional_settings'] = array(
250
    '#type' => 'vertical_tabs',
251
  );
252
253
  $form['common'] = array(
254
    '#type' => 'fieldset',
255
    '#title' => t('New content behavior'),
256
    '#group' => 'additional_settings',
257
    '#weight' => -10,
258
  );
259
  $form['common']['panels_common_default'] = array(
260
    '#type' => 'checkboxes',
261
    '#description' => t('Select the default behavior of new content added to the system. If checked, new content will automatically be immediately available to be added to Panels pages. If not checked, new content will not be available until specifically allowed here.'),
262
    '#options' => $default_options,
263
    '#default_value' => array_keys(array_filter($default_types)),
264
  );
265
266
  $form_state['skip'] = $skip;
267
  if ($skip) {
268
    $form['markup'] = array('#value' => t('<p>Click Submit to be presented with a complete list of available content types set to the defaults you selected.</p>'));
269
  }
270
  else {
271
    // Rebuild the entire list, setting appropriately from defaults. Give
272
    // each type its own checkboxes set unless it's 'single' in which
273
    // case it can go into our fake other set.
274
    $available_content_types = ctools_content_get_all_types();
275 64156087 Assos Assos
    $allowed_content_types = variable_get($module_name . '_allowed_types', array());
276 85ad3d82 Assos Assos
277
    foreach ($available_content_types as $id => $types) {
278
      foreach ($types as $type => $info) {
279
        $key = $id . '-' . $type;
280
        $checkboxes = empty($content_types[$id]['single']) ? $id : 'other';
281
        $options[$checkboxes][$key] = $info['title'];
282
        if (!isset($allowed_content_types[$key])) {
283
          $allowed[$checkboxes][$key] = isset($default_types[$id]) ? $default_types[$id] : $default_types['other'];
284
        }
285
        else {
286
          $allowed[$checkboxes][$key] = $allowed_content_types[$key];
287
        }
288
      }
289
    }
290
291
    $form['content_types'] = array(
292
      '#tree' => TRUE,
293
    );
294
295 64156087 Assos Assos
    // Cheat a bit.
296 85ad3d82 Assos Assos
    $content_types['other'] = array('title' => t('Other'), 'weight' => 10);
297
    foreach ($content_types as $id => $info) {
298
      if (isset($allowed[$id])) {
299
300
        $form['content_types'][$id] = array(
301
          '#type' => 'fieldset',
302
          '#group' => 'additional_settings',
303
          '#title' => t('Allowed @s content', array('@s' => $info['title'])),
304
        );
305
306
        $form['content_types'][$id]['options'] = array(
307
          '#prefix' => '<div class="panels-page-type-container">',
308
          '#suffix' => '</div>',
309
          '#type' => 'checkboxes',
310
          '#options' => $options[$id],
311
          '#default_value' => array_keys(array_filter($allowed[$id])),
312
          '#checkall' => TRUE,
313
        );
314
      }
315
    }
316
  }
317
318
  // Layout selection.
319
  panels_common_allowed_layouts_form($form, $form_state, $module_name);
320
321
  $form['allowed'] = array(
322
    '#type' => 'value',
323
    '#value' => isset($allowed) ? array_keys($allowed) : array(),
324
  );
325
326
  $form['module_name'] = array(
327
    '#type' => 'value',
328
    '#value' => $module_name,
329
  );
330
331
  $form['submit'] = array(
332
    '#type' => 'submit',
333
    '#value' => t('Save'),
334
  );
335
336
  ctools_add_css('panels_page', 'panels');
337
  return $form;
338
}
339
340
/**
341 64156087 Assos Assos
 * Submit hook for panels_common_settings.
342 85ad3d82 Assos Assos
 */
343
function panels_common_settings_validate($form, &$form_state) {
344
  panels_common_allowed_layouts_form_validate($form, $form_state);
345
}
346
347
/**
348 64156087 Assos Assos
 * Submit hook for panels_common_settings.
349 85ad3d82 Assos Assos
 */
350
function panels_common_settings_submit($form, &$form_state) {
351
  panels_common_allowed_layouts_form_submit($form, $form_state);
352
  $module_name = $form_state['values']['module_name'];
353
  variable_set($module_name . '_default', $form_state['values']['panels_common_default']);
354
  if (!$form_state['skip']) {
355 136a805a Assos Assos
    // Merge the broken apart array neatly back together.
356 85ad3d82 Assos Assos
    $allowed_content_types = array();
357 64156087 Assos Assos
    foreach ($form_state['values']['allowed'] as $allowed) {
358
      $values = $form_state['values']['content_types'][$allowed]['options'];
359
      // If new content of the type is not added, storing a lisy of disabled
360
      // content is not needed.
361
      if (!$form_state['values']['panels_common_default'][$allowed]) {
362
        $values = array_filter($values);
363 136a805a Assos Assos
      }
364 64156087 Assos Assos
      $allowed_content_types = array_merge($allowed_content_types, $values);
365 136a805a Assos Assos
    }
366 64156087 Assos Assos
    // Values from checkboxes are the same string as they key, but we only need
367
    // to store the boolean value.
368
    foreach ($allowed_content_types as &$value) {
369
      $value = (bool) $value;
370
    }
371
    variable_set($module_name . '_allowed_types', $allowed_content_types);
372 85ad3d82 Assos Assos
  }
373
  drupal_set_message(t('Your changes have been saved.'));
374
}
375
376
/**
377
 * Based upon the settings, get the allowed types for this node.
378
 */
379
function panels_common_get_allowed_types($module, $contexts = array(), $has_content = FALSE, $default_defaults = array(), $default_allowed_types = array()) {
380 64156087 Assos Assos
  // Get a list of all types that are available.
381 85ad3d82 Assos Assos
  $default_types = variable_get($module . '_default', $default_defaults);
382 64156087 Assos Assos
  $allowed_types = variable_get($module . '_allowed_types', $default_allowed_types);
383 85ad3d82 Assos Assos
384
  // By default, if they haven't gone and done the initial setup here,
385
  // let all 'other' types (which will be all types) be available.
386
  if (!isset($default_types['other'])) {
387
    $default_types['other'] = TRUE;
388
  }
389
390
  ctools_include('content');
391
  $content_types = ctools_content_get_available_types($contexts, $has_content, $allowed_types, $default_types);
392
393
  return $content_types;
394
}
395
396
/**
397
 * The FAPI code for generating an 'allowed layouts' selection form.
398
 *
399
 * NOTE: Because the Panels API does not guarantee a particular method of storing the data on allowed layouts,
400
 * it is not_possible for the Panels API to implement any checks that determine whether reductions in
401
 * the set of allowed layouts conflict with pre-existing layout selections. $displays in that category
402
 * will continue to function with their current layout as normal until the user/owner/admin attempts
403
 * to change layouts on that display, at which point they will have to select from the new set of
404
 * allowed layouts. If this is not the desired behavior for your client module, it's up to you to
405
 * write a validation routine that determines what should be done with conflicting layouts.
406
 *
407
 * Remember that changing layouts where panes have already been created can result in data loss;
408
 * consult panels_change_layout() to see how the Panels API handles that process. Running
409
 * drupal_execute('panels_change_layout', ...) is one possible starting point.
410
 *
411
 * @ingroup forms
412
 *
413
 * @param array $allowed_layouts
414 64156087 Assos Assos
 *   The set of allowed layouts that should be used as the default values
415
 *   for this form. If none is provided, then by default no layouts will be restricted.
416 85ad3d82 Assos Assos
 */
417
function panels_common_allowed_layouts_form(&$form, &$form_state, $module_name) {
418
  // Fetch our allowed layouts from variables.
419
  $allowed_layouts = panels_common_get_allowed_layout_object($module_name);
420
421
  $layouts = panels_get_layouts();
422
  foreach ($layouts as $id => $layout) {
423
    $options[$id] = panels_print_layout_icon($id, $layout, check_plain($layout['title']));
424
  }
425
426
  $form_state['allowed_layouts'] = &$allowed_layouts;
427
428 64156087 Assos Assos
  ctools_add_js('panels-base', 'panels');
429 85ad3d82 Assos Assos
  ctools_add_js('layout', 'panels');
430
431
  $form['layout_selection'] = array(
432
    '#type' => 'fieldset',
433
    '#title' => t('Select allowed layouts'),
434
    '#group' => 'additional_settings',
435
    '#weight' => 10,
436
  );
437
  $form['layout_selection']['layouts'] = array(
438
    '#type' => 'checkboxes',
439
    '#options' => $options,
440
    '#description' => t('Check the boxes for all layouts you want to allow users choose from when picking a layout. You must allow at least one layout.'),
441
    '#default_value' => array_keys(array_filter($allowed_layouts->allowed_layout_settings)),
442
    '#prefix' => '<div class="clearfix panels-layouts-checkboxes">',
443
    '#suffix' => '</div>',
444
    '#checkall' => TRUE,
445
  );
446
447
  return $form;
448
}
449
450
function panels_common_allowed_layouts_form_validate($form, &$form_state) {
451
  $selected = array_filter($form_state['values']['layouts']);
452
  if (empty($selected)) {
453
    form_set_error('layouts', 'You must choose at least one layout to allow.');
454
  }
455
}
456
457
function panels_common_allowed_layouts_form_submit($form, &$form_state) {
458
  foreach ($form_state['values']['layouts'] as $layout => $setting) {
459
    $form_state['allowed_layouts']->allowed_layout_settings[$layout] = (bool) $setting;
460
  }
461
  $form_state['allowed_layouts']->save();
462
}
463
464
/**
465
 * Get the allowed layout object for the given module.
466
 */
467
function panels_common_get_allowed_layout_object($module_name) {
468 64156087 Assos Assos
  $allowed_layouts = unserialize(variable_get($module_name . "_allowed_layouts", serialize('')));
469 85ad3d82 Assos Assos
470 64156087 Assos Assos
  // If no parameter was provided, or the variable_get failed.
471 85ad3d82 Assos Assos
  if (!$allowed_layouts) {
472 64156087 Assos Assos
    // Still no dice. simply creates a dummy version where all layouts
473 85ad3d82 Assos Assos
    // are allowed.
474
    $allowed_layouts = new panels_allowed_layouts();
475
    $allowed_layouts->allow_new = TRUE;
476
    $allowed_layouts->module_name = $module_name;
477
  }
478
479 64156087 Assos Assos
  // Sanitize allowed layout listing; this is redundant if the
480
  // $allowed_layouts param was null, but the data is cached anyway.
481 85ad3d82 Assos Assos
  $allowed_layouts->sync_with_available();
482
483
  return $allowed_layouts;
484
}
485
486
/**
487
 * Get the allowed layouts for the given module.
488
 */
489
function panels_common_get_allowed_layouts($module_name) {
490 5a7e6170 Florent Torregrosa
  ctools_include('plugins', 'panels');
491 85ad3d82 Assos Assos
  $available_layouts = panels_get_layouts();
492
  if (empty($module_name)) {
493
    return $available_layouts;
494
  }
495 64156087 Assos Assos
  elseif (is_object($module_name)) {
496 85ad3d82 Assos Assos
    $allowed_layouts = $module_name;
497
  }
498
  else {
499
    $allowed_layouts = panels_common_get_allowed_layout_object($module_name);
500
  }
501
502
  $allowed = array_filter($allowed_layouts->allowed_layout_settings);
503
  $order = array();
504
  foreach ($available_layouts as $name => $plugin) {
505
    if (!empty($allowed[$name])) {
506
      $order[$name] = $plugin['category'] . ':' . $plugin['title'];
507
    }
508
  }
509
510 64156087 Assos Assos
  // Sort.
511 85ad3d82 Assos Assos
  $layouts = array();
512
513
  asort($order);
514
  foreach ($order as $name => $junk) {
515
    $layouts[$name] = $available_layouts[$name];
516
  }
517
518
  return $layouts;
519
}
520
521
/**
522
 * Create a visible list of content in a display.
523
 * Note that the contexts must be pre-loaded.
524
 */
525
function theme_panels_common_content_list($vars) {
526
  $display = $vars['display'];
527
528
  $layout = panels_get_layout($display->layout);
529
  $content = '<dl class="content-list">';
530
  foreach (panels_get_regions($layout, $display) as $panel_id => $title) {
531
    $content .= "<dt>$title</dt><dd>";
532
    if (!empty($display->panels[$panel_id])) {
533
      $content .= '<ol>';
534
      foreach ($display->panels[$panel_id] as $pid) {
535
        $content .= '<li>' . panels_get_pane_title($display->content[$pid], $display->context) . '</li>';
536
      }
537
      $content .= '</ol>';
538
    }
539
    else {
540
      $content .= t('Empty');
541
    }
542
    $content .= '</dd>';
543
  }
544
  $content .= '</dl>';
545
  return $content;
546
}
547
548
/**
549
 * Print a selector of layouts, each linked to the next step.
550
 *
551
 * Most operations use radio buttons for selecting layouts, but some will
552
 * give each layout as a link that goes to the next step. This function
553
 * makes it easy to simply provide a list of allowed layouts and the base
554
 * path.
555
 *
556
 * One limitation is that it will only append the layout name to the end, so
557
 * if the actual layout name is needed in the middle, that can't happen.
558
 *
559
 * @return
560
 *   The rendered output.
561
 */
562
function panels_common_print_layout_links($layouts, $base_path, $link_options = array(), $current_layout = NULL) {
563
  $output = '';
564
565
  $categories = array();
566
  ctools_include('cleanstring');
567
  $default_category = '';
568
  foreach ($layouts as $id => $layout) {
569
    $category = ctools_cleanstring($layout['category']);
570
571
    $categories[$category] = $layout['category'];
572
    if ($id == $current_layout) {
573
      $default_category = $category;
574
    }
575
576
    $options[$category][$id] = panels_print_layout_link($id, $layout, $base_path . '/' . $id, $link_options, $current_layout);
577
  }
578
579
  $form = array();
580
  $form['categories'] = array(
581
    '#title' => t('Category'),
582
    '#type' => 'select',
583
    '#options' => $categories,
584
    '#name' => 'categories',
585
    '#id' => 'edit-categories',
586
    '#value' => $default_category,
587
    '#parents' => array('categories'),
588
    '#access' => (count($categories) > 1) ? TRUE : FALSE,
589
  );
590
591
  $output .= drupal_render($form);
592
593
  $output .= '<div class="panels-choose-layout panels-layouts-checkboxes clearfix">';
594
595
  // We're doing these dependencies completely manualy, which is unusual, but
596
  // the process code only supports doing them in a form.
597
  // @todo modify dependent.inc to make this easier.
598
  $dependencies = array();
599
  foreach ($options as $category => $links) {
600
    $dependencies['panels-layout-category-' . $category] = array(
601
      'values' => array('edit-categories' => array($category)),
602
      'num' => 1,
603
      'type' => 'hide',
604
    );
605
606
    $output .= '<div id="panels-layout-category-' . $category . '-wrapper">';
607
    $output .= '<div id="panels-layout-category-' . $category . '" class="form-checkboxes clearfix">';
608
    $output .= (count($categories) > 1) ? '<div class="panels-layouts-category">' . $categories[$category] . '</div>' : '';
609
610
    foreach ($links as $key => $link) {
611
      $output .= $link;
612
    }
613
    $output .= '</div></div>';
614
  }
615
616
  $output .= '</div>';
617
618
  ctools_add_js('dependent');
619
  $js['CTools']['dependent'] = $dependencies;
620
  drupal_add_js($js, 'setting');
621
622
  return $output;
623
}