Projet

Général

Profil

Paste
Télécharger (50,6 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ctools / page_manager / plugins / tasks / page.admin.inc @ c304a780

1
<?php
2

    
3
/**
4
 * @file
5
 * Administrative functions for the page subtasks.
6
 *
7
 * These are attached to the menu system in page.inc via the hook_menu
8
 * delegation. They are included here so that this code is loaded
9
 * only when needed.
10
 */
11

    
12
/**
13
 * Delegated implementation of hook_menu().
14
 */
15
function page_manager_page_menu(&$items, $task) {
16
  // Set up access permissions.
17
  $access_callback = isset($task['admin access callback']) ? $task['admin access callback'] : 'user_access';
18
  $access_arguments = isset($task['admin access arguments']) ? $task['admin access arguments'] : array('administer page manager');
19

    
20
  $base = array(
21
    'access callback' => $access_callback,
22
    'access arguments' => $access_arguments,
23
    'file' => 'plugins/tasks/page.admin.inc',
24
  );
25

    
26
  $items['admin/structure/pages/add'] = array(
27
    'title' => 'Add custom page',
28
    'page callback' => 'page_manager_page_add_subtask',
29
    'page arguments' => array(),
30
    'type' => MENU_LOCAL_ACTION,
31
  ) + $base;
32

    
33
  $items['admin/structure/pages/import'] = array(
34
    'title' => 'Import page',
35
    'page callback' => 'drupal_get_form',
36
    'page arguments' => array('page_manager_page_import_subtask', 'page'),
37
    'type' => MENU_LOCAL_ACTION,
38
  ) + $base;
39
  if ($access_callback == 'user_access') {
40
    $items['admin/structure/pages/import']['access callback'] = 'ctools_access_multiperm';
41
    $items['admin/structure/pages/import']['access arguments'][] = 'use ctools import';
42
  }
43

    
44
  // AJAX callbacks for argument modal.
45
  $items['admin/structure/pages/argument'] = array(
46
    'page callback' => 'page_manager_page_subtask_argument_ajax',
47
    'type' => MENU_CALLBACK,
48
  ) + $base;
49

    
50
  // Add menu entries for each subtask.
51
  foreach (page_manager_page_load_all() as $subtask_id => $subtask) {
52
    if (!empty($subtask->disabled)) {
53
      continue;
54
    }
55

    
56
    if (!isset($subtask->access['type'])) {
57
      $subtask->access['type'] = 'none';
58
    }
59
    if (!isset($subtask->access['settings'])) {
60
      $subtask->access['settings'] = NULL;
61
    }
62

    
63
    $path             = array();
64
    $page_arguments   = array((string) $subtask_id);
65
    $access_arguments = array($subtask->access);
66
    $load_arguments   = array($subtask_id, '%index', '%map');
67

    
68
    // Replace named placeholders with our own placeholder to load contexts.
69
    $position = 0;
70

    
71
    foreach (explode('/', $subtask->path) as $bit) {
72
      // Remove things like double slashes completely.
73
      if (!isset($bit) || $bit === '') {
74
        continue;
75
      }
76

    
77
      if ($bit[0] == '%' && $bit != '%') {
78
        $placeholder = '%pm_arg';
79

    
80
        // Chop off that %.
81
        $name = substr($bit, 1);
82

    
83
        // Check to see if the argument plugin wants to use a different
84
        // placholder. This will allow to_args.
85
        if (!empty($subtask->arguments[$name])) {
86
          ctools_include('context');
87
          if (!empty($subtask->arguments[$name]['name'])) {
88
            $plugin = ctools_get_argument($subtask->arguments[$name]['name']);
89
            if (isset($plugin['path placeholder'])) {
90
              if (function_exists($plugin['path placeholder'])) {
91
                $placeholder = $plugin['path placeholder']($subtask->arguments[$name]);
92
              }
93
              else {
94
                $placeholder = $plugin['path placeholder'];
95
              }
96
            }
97
          }
98
        }
99
        // If an argument, swap it out with our argument loader and make sure
100
        // the argument gets passed through to the page callback.
101
        $path[]             = $placeholder;
102
        $page_arguments[]   = $position;
103
        $access_arguments[] = $position;
104
      }
105
      elseif ($bit[0] != '!') {
106
        $path[] = $bit;
107
      }
108

    
109
      // Increment position. We do it like this to skip empty items that
110
      // could happen from erroneous paths like: this///that.
111
      $position++;
112
    }
113

    
114
    $menu_path = implode('/', $path);
115

    
116
    $items[$menu_path] = page_manager_page_menu_item($task, $subtask->menu, $access_arguments, $page_arguments, $load_arguments);
117

    
118
    // Add a parent menu item if one is configured.
119
    if (isset($subtask->menu['type']) && $subtask->menu['type'] == 'default tab') {
120
      array_pop($path);
121
      $parent_path = implode('/', $path);
122
      $items[$parent_path] = page_manager_page_menu_item($task, $subtask->menu['parent'], $access_arguments, $page_arguments, $load_arguments);
123
    }
124
  }
125
}
126

    
127
/**
128
 * Create a menu item for page manager pages.
129
 *
130
 * @param $menu
131
 *   The configuration to use. It will contain a type, and depending on the
132
 *   type may also contain weight, title and name. These are presumed to have
133
 *   been configured from the UI.
134
 * @param $access_arguments
135
 *   Arguments that go with ctools_access_menu; it should be loaded with
136
 *   the access plugin type, settings, and positions of any arguments that
137
 *   may produce contexts.
138
 * @param $page_arguments
139
 *   This should be seeded with the subtask name for easy loading and like
140
 *   the access arguments above should contain positions of arguments so
141
 *   that the menu system passes contexts through.
142
 * @param $load_arguments
143
 *   Arguments to send to the arg loader; should be the subtask id and '%index'.
144
 */
145
function page_manager_page_menu_item($task, $menu, $access_arguments, $page_arguments, $load_arguments) {
146
  $item = array(
147
    'access callback' => 'ctools_access_menu',
148
    'access arguments' => $access_arguments,
149
    'page callback' => 'page_manager_page_execute',
150
    'page arguments' => $page_arguments,
151
    'load arguments' => $load_arguments,
152
    'file' => 'plugins/tasks/page.inc',
153
  );
154

    
155
  if (isset($menu['title'])) {
156
    $item['title'] = $menu['title'];
157
  }
158
  if (isset($menu['weight'])) {
159
    $item['weight'] = $menu['weight'];
160
  }
161

    
162
  if (empty($menu['type'])) {
163
    $menu['type'] = 'none';
164
  }
165

    
166
  switch ($menu['type']) {
167
    case 'none':
168
    default:
169
      $item['type'] = MENU_CALLBACK;
170
      break;
171

    
172
    case 'normal':
173
      $item['type'] = MENU_NORMAL_ITEM;
174
      // Insert item into the proper menu.
175
      $item['menu_name'] = $menu['name'];
176
      break;
177

    
178
    case 'tab':
179
      $item['type'] = MENU_LOCAL_TASK;
180
      break;
181

    
182
    case 'action':
183
      $item['type'] = MENU_LOCAL_ACTION;
184
      break;
185

    
186
    case 'default tab':
187
      $item['type'] = MENU_DEFAULT_LOCAL_TASK;
188
      break;
189
  }
190

    
191
  return $item;
192
}
193

    
194
/**
195
 * Page callback to add a subtask.
196
 */
197
function page_manager_page_add_subtask($task_name = NULL, $step = NULL) {
198
  ctools_include('context');
199
  $task = page_manager_get_task('page');
200
  $task_handler_plugins = page_manager_get_task_handler_plugins($task);
201
  if (empty($task_handler_plugins)) {
202
    drupal_set_message(t('There are currently no variants available and a page may not be added. Perhaps you need to install the Panels module to get a variant?'), 'error');
203
    return ' ';
204
  }
205

    
206
  $form_info = array(
207
    'id' => 'page_manager_add_page',
208
    'show trail' => TRUE,
209
    'show back' => TRUE,
210
    'show return' => FALSE,
211
    'next callback' => 'page_manager_page_add_subtask_next',
212
    'finish callback' => 'page_manager_page_add_subtask_finish',
213
    'return callback' => 'page_manager_page_add_subtask_finish',
214
    'cancel callback' => 'page_manager_page_add_subtask_cancel',
215
    'add order' => array(
216
      'basic' => t('Basic settings'),
217
      'argument' => t('Argument settings'),
218
      'access' => t('Access control'),
219
      'menu' => t('Menu settings'),
220
    ),
221
    'forms' => array(
222
      'basic' => array(
223
        'form id' => 'page_manager_page_form_basic',
224
      ),
225
      'access' => array(
226
        'form id' => 'page_manager_page_form_access',
227
      ),
228
      'menu' => array(
229
        'form id' => 'page_manager_page_form_menu',
230
      ),
231
      'argument' => array(
232
        'form id' => 'page_manager_page_form_argument',
233
      ),
234
    ),
235
  );
236

    
237
  if ($task_name) {
238
    $page = page_manager_get_page_cache($task_name);
239
    if (empty($page)) {
240
      return MENU_NOT_FOUND;
241
    }
242

    
243
    $form_info['path'] = "admin/structure/pages/add/$task_name/%step";
244
  }
245
  else {
246
    $new_page = page_manager_page_new();
247
    $new_page->name = NULL;
248

    
249
    $page = new stdClass();
250
    page_manager_page_new_page_cache($new_page, $page);
251
    $form_info['path'] = 'admin/structure/pages/add/%task_name/%step';
252
  }
253

    
254
  if ($step && $step != 'basic') {
255
    $handler_plugin = page_manager_get_task_handler($page->handler);
256

    
257
    $form_info['forms'] += $handler_plugin['forms'];
258

    
259
    if (isset($page->forms)) {
260
      foreach ($page->forms as $id) {
261
        if (isset($form_info['add order'][$id])) {
262
          $form_info['order'][$id] = $form_info['add order'][$id];
263
        }
264
        elseif (isset($handler_plugin['add features'][$id])) {
265
          $form_info['order'][$id] = $handler_plugin['add features'][$id];
266
        }
267
        elseif (isset($handler_plugin['required forms'][$id])) {
268
          $form_info['order'][$id] = $handler_plugin['required forms'][$id];
269
        }
270
      }
271
    }
272
    else {
273
      $form_info['order'] = $form_info['add order'];
274
    }
275

    
276
    // This means we just submitted our form from the default list
277
    // of steps, which we've traded in for a newly generated list of
278
    // steps above. We need to translate this 'next' step into what
279
    // our questions determined would be next.
280
    if ($step == 'next') {
281
      $keys = array_keys($form_info['order']);
282
      // Get rid of 'basic' from the list of forms.
283
      array_shift($keys);
284
      $step = array_shift($keys);
285

    
286
      // If $step == 'basic' at this point, we were not presented with any
287
      // additional forms at all. Let's just save and go!
288
      if ($step == 'basic') {
289
        page_manager_save_page_cache($page);
290
        // Redirect to the new page's task handler editor.
291
        drupal_goto(page_manager_edit_url($page->task_name));
292
      }
293
    }
294
  }
295
  else {
296
    $form_info['show trail'] = FALSE;
297
    $form_info['order'] = array(
298
      'basic' => t('Basic settings'),
299
      'next' => t('A meaningless second page'),
300
    );
301
  }
302

    
303
  ctools_include('wizard');
304
  $form_state = array(
305
    'task' => $task,
306
    'subtask' => $page->subtask,
307
    'page' => &$page,
308
    'type' => 'add',
309
    'task_id' => 'page',
310
    'task_name' => $page->task_name,
311
    'creating' => TRUE,
312
  );
313

    
314
  if (!empty($page->handlers)) {
315
    $keys = array_keys($page->handlers);
316
    $key = array_shift($keys);
317
    $form_state['handler'] = &$page->handlers[$key];
318
    $form_state['handler_id'] = $key;
319
  }
320

    
321
  $output = ctools_wizard_multistep_form($form_info, $step, $form_state);
322

    
323
  if (!$output) {
324
    // redirect.
325
    drupal_redirect_form(array(), $form_state['redirect']);
326
  }
327

    
328
  return $output;
329
}
330

    
331
/**
332
 * Callback generated when the add page process is finished.
333
 */
334
function page_manager_page_add_subtask_finish(&$form_state) {
335
  $page = &$form_state['page'];
336
  // Update the cache with changes.
337
  page_manager_set_page_cache($page);
338

    
339
  $handler = $form_state['handler'];
340
  $handler_plugin = page_manager_get_task_handler($handler->handler);
341

    
342
  // Redirect to the new page's task handler editor.
343
  if (isset($handler_plugin['add finish'])) {
344
    $form_state['redirect'] = page_manager_edit_url($page->task_name, array('handlers', $handler->name, $handler_plugin['add finish']));
345
  }
346
  else {
347
    $form_state['redirect'] = page_manager_edit_url($page->task_name);
348
  }
349
  return;
350
}
351

    
352
/**
353
 * Callback generated when the 'next' button is clicked.
354
 *
355
 * All we do here is store the cache.
356
 */
357
function page_manager_page_add_subtask_next(&$form_state) {
358
  if (empty($form_state['task_name']) || $form_state['task_name'] == 'page') {
359
    // We may not have known the path to go next, because we didn't yet know the
360
    // task name. This fixes that.
361
    $form_state['form_info']['path'] = str_replace('%task_name', $form_state['page']->task_name, $form_state['form_info']['path']);
362

    
363
    $form_state['redirect'] = ctools_wizard_get_path($form_state['form_info'], $form_state['clicked_button']['#next']);
364
  }
365

    
366
  // Update the cache with changes.
367
  page_manager_set_page_cache($form_state['page']);
368
}
369

    
370
/**
371
 * Callback generated when the 'cancel' button is clicked.
372
 *
373
 * All we do here is clear the cache.
374
 */
375
function page_manager_page_add_subtask_cancel(&$form_state) {
376
  // Wipe all our stored changes.
377
  if (isset($form_state['page']->task_name)) {
378
    page_manager_clear_page_cache($form_state['page']->task_name);
379
  }
380
}
381

    
382
/**
383
 * Basic settings form for a page manager page.
384
 */
385
function page_manager_page_form_basic($form, &$form_state) {
386
  $page = &$form_state['page']->subtask['subtask'];
387
  $task = $form_state['task'];
388

    
389
  $form['admin_title'] = array(
390
    '#type' => 'textfield',
391
    '#title' => t('Administrative title'),
392
    '#description' => t('The name of this page. This will appear in the administrative interface to easily identify it.'),
393
    '#default_value' => $page->admin_title,
394
  );
395

    
396
  $form['name'] = array(
397
    '#type' => 'machine_name',
398
    '#title' => t('Machine name'),
399
    '#machine_name' => array(
400
      'exists' => 'page_manager_page_load',
401
      'source' => array('admin_title'),
402
    ),
403
    '#description' => t('The machine readable name of this page. It must be unique, and it must contain only alphanumeric characters and underscores. Once created, you will not be able to change this value!'),
404
    '#default_value' => $page->name,
405
  );
406

    
407
  if (isset($page->pid) || empty($form_state['creating'])) {
408
    $form['name']['#disabled'] = TRUE;
409
    $form['name']['#value'] = $page->name;
410
  }
411

    
412
  $form['admin_description'] = array(
413
    '#type' => 'textarea',
414
    '#title' => t('Administrative description'),
415
    '#description' => t('A description of what this page is, does or is for, for administrative use.'),
416
    '#default_value' => $page->admin_description,
417
  );
418

    
419
  // Path.
420
  $form['path'] = array(
421
    '#type' => 'textfield',
422
    '#title' => t('Path'),
423
    '#description' => t('The URL path to get to this page. You may create named placeholders for variable parts of the path by using %name for required elements and !name for optional elements. For example: "node/%node/foo", "forum/%forum" or "dashboard/!input". These named placeholders can be turned into contexts on the arguments form.'),
424
    '#default_value' => $page->path,
425
    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='),
426
  );
427

    
428
  $frontpage = variable_get('site_frontpage', 'node');
429

    
430
  $path = array();
431
  if ($page->path) {
432
    foreach (explode('/', $page->path) as $bit) {
433
      if ($bit[0] != '!') {
434
        $path[] = $bit;
435
      }
436
    }
437
  }
438

    
439
  $path = implode('/', $path);
440

    
441
  if (empty($path) || $path != $frontpage) {
442
    $form['frontpage'] = array(
443
      '#type' => 'checkbox',
444
      '#default_value' => !empty($page->make_frontpage),
445
      '#title' => t('Make this your site home page.'),
446
      '#description' => t('To set this panel as your home page you must create a unique path name with no % placeholders in the path. The site home page is currently set to %homepage on the !siteinfo configuration form.', array('!siteinfo' => l(t('Site Information'), 'admin/config/system/site-information'), '%homepage' => '/' . $frontpage)),
447
    );
448
    $form['admin_paths'] = array(
449
      '#type' => 'checkbox',
450
      '#default_value' => !empty($page->conf['admin_paths']),
451
      '#title' => t('Use this page in an admin overlay.'),
452
      '#description' => t('Admin overlays are used in many places in Drupal 7 and administrative custom pages should probably utilize this feature.'),
453
    );
454
  }
455
  elseif ($path == $frontpage) {
456
    $form['frontpage_markup'] = array(
457
      '#value' => '<b>' . t('This page is currently set to be your site home page. This can be modified on the !siteinfo configuration form.', array('!siteinfo' => l(t('Site Information'), 'admin/settings/site-information'))) . '</b>',
458
    );
459

    
460
    $form['frontpage'] = array(
461
      '#type' => 'value',
462
      '#value' => TRUE,
463
    );
464
  }
465

    
466
  if (!isset($page->pid) && !empty($form_state['creating'])) {
467
    $features['default'] = array(
468
      'access' => t('Access control'),
469
      'menu' => t('Visible menu item'),
470
    );
471

    
472
    module_load_include('inc', 'page_manager', 'page_manager.admin');
473
    $form = page_manager_handler_add_form($form, $form_state, $features);
474
  }
475

    
476
  return $form;
477
}
478

    
479
function page_manager_page_form_basic_validate_filter($value) {
480
  return $value === -1;
481
}
482

    
483
/**
484
 * Validate the basic form.
485
 */
486
function page_manager_page_form_basic_validate(&$form, &$form_state) {
487
  // Ensure path is unused by other pages.
488
  $page = $form_state['page']->subtask['subtask'];
489
  $name = !empty($form_state['values']['name']) ? $form_state['values']['name'] : $page->name;
490
  if (empty($name)) {
491
    form_error($form['name'], t('Name is required.'));
492
  }
493

    
494
  // If this is new, make sure the name is unique:
495
  if (empty($page->name)) {
496
    $test = page_manager_page_load($name);
497
    if ($test) {
498
      form_error($form['name'], t('That name is used by another page: @page', array('@page' => $test->admin_title)));
499
    }
500

    
501
    // Ensure name fits the rules:
502
    if (preg_match('/[^a-zA-Z0-9_]/', $form_state['values']['name'])) {
503
      form_error($form['name'], t('Page name must be alphanumeric or underscores only.'));
504
    }
505
  }
506

    
507
  $pages = page_manager_page_load_all();
508
  foreach ($pages as $test) {
509
    if ($test->name != $name && $test->path == $form_state['values']['path'] && empty($test->disabled)) {
510
      form_error($form['path'], t('That path is used by another page: @page', array('@page' => $test->admin_title)));
511
    }
512
  }
513

    
514
  // Ensure path is unused by things NOT pages. We do the double check because
515
  // we're checking against our page callback.
516
  $path = array();
517
  if (empty($form_state['values']['path'])) {
518
    form_error($form['path'], t('Path is required.'));
519
    // Stop processing here if there is no path.
520
    return;
521
  }
522

    
523
  $found = FALSE;
524
  $error = FALSE;
525
  foreach (explode('/', $form_state['values']['path']) as $position => $bit) {
526
    if (!isset($bit) || $bit === '') {
527
      continue;
528
    }
529

    
530
    if ($bit == '%' || $bit == '!') {
531
      form_error($form['path'], t('You cannot have an unnamed placeholder (% or ! by itself). Please name your placeholder by adding a short piece of descriptive text to the % or !, such as %user or %node.'));
532
    }
533

    
534
    if ($bit[0] == '%') {
535
      if ($found) {
536
        form_error($form['path'], t('You cannot have a dynamic path element after an optional path element.'));
537
      }
538

    
539
      if ($position == 0) {
540
        form_error($form['path'], t('The first element in a path may not be dynamic.'));
541
      }
542

    
543
      $path[] = '%';
544
    }
545
    elseif ($bit[0] == '!') {
546
      $found = TRUE;
547
    }
548
    else {
549
      if ($found) {
550
        form_error($form['path'], t('You cannot have a static path element after an optional path element.'));
551
      }
552
      $path[] = $bit;
553
    }
554
  }
555

    
556
  // Check to see if something that isn't a page manager page is using the path.
557
  $path = implode('/', $path);
558
  $result = db_query('SELECT * FROM {menu_router} WHERE path = :path', array(':path' => $path));
559
  foreach ($result as $router) {
560
    if ($router->page_callback != 'page_manager_page_execute') {
561
      form_error($form['path'], t('That path is already in use. This system cannot override existing paths.'));
562
    }
563
  }
564

    
565
  // Ensure the path is not already an alias to something else.
566
  if (strpos($path, '%') === FALSE) {
567
    $alias = db_query('SELECT alias, source FROM {url_alias} WHERE alias = :path', array(':path' => $path))->fetchObject();
568
    if ($alias) {
569
      form_error($form['path'], t('That path is currently assigned to be an alias for @alias. This system cannot override existing aliases.', array('@alias' => $alias->source)));
570
    }
571
  }
572
  else {
573
    if (!empty($form_state['values']['frontpage'])) {
574
      form_error($form['path'], t('You cannot make this page your site home page if it uses % placeholders.'));
575
    }
576
  }
577

    
578
  // Ensure path is properly formed.
579
  $args = page_manager_page_get_named_arguments($form_state['values']['path']);
580
  if ($invalid_args = array_filter($args, 'page_manager_page_form_basic_validate_filter')) {
581
    foreach ($invalid_args as $arg => $position) {
582
      form_error($form['path'], t('Duplicated argument %arg', array('%arg' => $arg)));
583
    }
584
  }
585

    
586
  if (isset($args['%'])) {
587
    form_error($form['path'], t('Invalid arg <em>%</em>. All arguments must be named with keywords.'));
588
  }
589

    
590
  $form_state['arguments'] = $args;
591
}
592

    
593
/**
594
 * Store the values from the basic settings form.
595
 */
596
function page_manager_page_form_basic_submit(&$form, &$form_state) {
597
  $page = &$form_state['page']->subtask['subtask'];
598
  $cache = &$form_state['page'];
599

    
600
  // If this is a new thing, then we have to do a bunch of setup to create
601
  // the cache record with the right ID and some basic data that we could
602
  // not know until we asked the user some questions.
603
  if (!isset($page->pid) && !empty($form_state['creating'])) {
604
    // Update the data with our new name.
605
    $page->name = $form_state['values']['name'];
606
    $form_state['page']->task_name = page_manager_make_task_name($form_state['task_id'], $page->name);
607
    $cache->handler = $form_state['values']['handler'];
608
    $cache->subtask_id = $page->name;
609
    $plugin = page_manager_get_task_handler($cache->handler);
610

    
611
    // If they created and went back, there might be old, dead handlers
612
    // that are not going to be added.
613
    //
614
    // Remove them:
615
    $cache->handlers = array();
616
    $cache->handler_info = array();
617

    
618
    // Create a new handler.
619
    $handler = page_manager_new_task_handler($plugin);
620
    $title = !empty($form_state['values']['title']) ? $form_state['values']['title'] : $plugin['title'];
621
    page_manager_handler_add_to_page($cache, $handler, $title);
622

    
623
    // Figure out which forms to present them with.
624
    $cache->forms = array();
625
    // This one is always there.
626
    $cache->forms[] = 'basic';
627
    if (!empty($form_state['arguments'])) {
628
      $cache->forms[] = 'argument';
629
    }
630

    
631
    $features = $form_state['values']['features'];
632
    $cache->forms = array_merge($cache->forms, array_keys(array_filter($features['default'])));
633
    if (isset($features[$form_state['values']['handler']])) {
634
      $cache->forms = array_merge($cache->forms, array_keys(array_filter($features[$form_state['values']['handler']])));
635
    }
636

    
637
    if (isset($plugin['required forms'])) {
638
      $cache->forms = array_merge($cache->forms, array_keys($plugin['required forms']));
639
    }
640
  }
641

    
642
  $page->admin_title = $form_state['values']['admin_title'];
643
  $cache->subtask['admin title'] = check_plain($form_state['values']['admin_title']);
644

    
645
  $page->admin_description = $form_state['values']['admin_description'];
646
  $cache->subtask['admin description'] = filter_xss_admin($form_state['values']['admin_description']);
647

    
648
  if ($page->path != $form_state['values']['path']) {
649
    $page->path = $form_state['values']['path'];
650
    page_manager_page_recalculate_arguments($page);
651
    $cache->path_changed = TRUE;
652
  }
653

    
654
  $page->make_frontpage = !empty($form_state['values']['frontpage']);
655
  $page->conf['admin_paths'] = !empty($form_state['values']['admin_paths']);
656
}
657

    
658
/**
659
 * Form to handle menu item controls.
660
 */
661
function page_manager_page_form_menu($form, &$form_state) {
662
  ctools_include('dependent');
663
  $form['menu'] = array(
664
    '#prefix' => '<div class="clearfix">',
665
    '#suffix' => '</div>',
666
    '#tree' => TRUE,
667
  );
668

    
669
  $menu = $form_state['page']->subtask['subtask']->menu;
670
  if (empty($menu)) {
671
    $menu = array(
672
      'type' => 'none',
673
      'title' => '',
674
      'weight' => 0,
675
      'name' => 'navigation',
676
      'parent' => array(
677
        'type' => 'none',
678
        'title' => '',
679
        'weight' => 0,
680
        'name' => 'navigation',
681
      ),
682
    );
683
  }
684

    
685
  $form['menu']['type'] = array(
686
    '#title' => t('Type'),
687
    '#type' => 'radios',
688
    '#options' => array(
689
      'none' => t('No menu entry'),
690
      'normal' => t('Normal menu entry'),
691
      'tab' => t('Menu tab'),
692
      'default tab' => t('Default menu tab'),
693
      'action' => t('Local action'),
694
    ),
695
    '#default_value' => $menu['type'],
696
  );
697

    
698
  $form['menu']['title'] = array(
699
    '#title' => t('Title'),
700
    '#type' => 'textfield',
701
    '#default_value' => $menu['title'],
702
    '#description' => t('If set to normal or tab, enter the text to use for the menu item. Renaming the menu item using the Drupal menu system (admin/structure/menu) will override this, even if it is renamed again here.'),
703
    '#dependency' => array('radio:menu[type]' => array('normal', 'tab', 'default tab', 'action')),
704
  );
705

    
706
  list($major, $minor) = explode('.', VERSION, 2);
707

    
708
  // Only display the menu selector if menu module is enabled.
709
  if (module_exists('menu')) {
710
    $form['menu']['name'] = array(
711
      '#title' => t('Menu'),
712
      '#type' => 'select',
713
      '#options' => menu_get_menus(),
714
      '#default_value' => $menu['name'],
715
      '#description' => t('Insert item into an available menu.'),
716
      '#dependency' => array('radio:menu[type]' => array('normal')),
717
    );
718
  }
719
  else {
720
    $form['menu']['name'] = array(
721
      '#type' => 'value',
722
      '#value' => $menu['name'],
723
    );
724
    $form['menu']['markup'] = array(
725
      '#value' => t('Menu selection requires the activation of menu module.'),
726
    );
727
  }
728
  $form['menu']['weight'] = array(
729
    '#title' => t('Weight'),
730
    '#type' => 'textfield',
731
    '#default_value' => isset($menu['weight']) ? $menu['weight'] : 0,
732
    '#description' => t('The lower the weight the higher/further left it will appear.'),
733
    '#dependency' => array('radio:menu[type]' => array('normal', 'tab', 'default tab', 'action')),
734
  );
735

    
736
  $form['menu']['parent']['type'] = array(
737
    '#prefix' => '<div id="edit-menu-parent-type-wrapper">',
738
    '#suffix' => '</div>',
739
    '#title' => t('Parent menu item'),
740
    '#type' => 'radios',
741
    '#options' => array('none' => t('No menu entry'), 'normal' => t('Normal menu item'), 'tab' => t('Menu tab')),
742
    '#default_value' => $menu['parent']['type'],
743
    '#description' => t('When providing a menu item as a default tab, Drupal needs to know what the parent menu item of that tab will be. Sometimes the parent will already exist, but other times you will need to have one created. The path of a parent item will always be the same path with the last part left off. i.e, if the path to this view is <em>foo/bar/baz</em>, the parent path would be <em>foo/bar</em>.'),
744
    '#dependency' => array('radio:menu[type]' => array('default tab')),
745
  );
746
  $form['menu']['parent']['title'] = array(
747
    '#title' => t('Parent item title'),
748
    '#type' => 'textfield',
749
    '#default_value' => $menu['parent']['title'],
750
    '#description' => t('If creating a parent menu item, enter the title of the item.'),
751
    '#dependency' => array('radio:menu[type]' => array('default tab'), 'radio:menu[parent][type]' => array('normal', 'tab')),
752
    '#dependency_count' => 2,
753
  );
754
  // Only display the menu selector if menu module is enabled.
755
  if (module_exists('menu')) {
756
    $form['menu']['parent']['name'] = array(
757
      '#title' => t('Parent item menu'),
758
      '#type' => 'select',
759
      '#options' => menu_get_menus(),
760
      '#default_value' => $menu['parent']['name'],
761
      '#description' => t('Insert item into an available menu.'),
762
      '#dependency' => array('radio:menu[type]' => array('default tab'), 'radio:menu[parent][type]' => array('normal')),
763
      '#dependency_count' => 2,
764
    );
765
  }
766
  else {
767
    $form['menu']['parent']['name'] = array(
768
      '#type' => 'value',
769
      '#value' => $menu['parent']['name'],
770
    );
771
  }
772
  $form['menu']['parent']['weight'] = array(
773
    '#title' => t('Parent weight'),
774
    '#type' => 'textfield',
775
    '#default_value' => $menu['parent']['weight'],
776
    '#size' => 5,
777
    '#description' => t('Enter the weight of the parent item. The lower the number, the more to the left it will be.'),
778
    '#dependency' => array('radio:menu[type]' => array('default tab'), 'radio:menu[parent][type]' => array('tab', 'normal')),
779
    '#dependency_count' => 2,
780
  );
781

    
782
  return $form;
783
}
784

    
785
/**
786
 * Validate handler for the menu form for add/edit page task.
787
 */
788
function page_manager_page_form_menu_validate(&$form, &$form_state) {
789
  // If setting a 'normal' menu entry, make sure that any placeholders
790
  // support the to_arg stuff.
791
  if ($form_state['values']['menu']['type'] == 'normal') {
792
    $page = $form_state['page']->subtask['subtask'];
793

    
794
    foreach (explode('/', $page->path) as $bit) {
795
      if (!isset($bit) || $bit === '') {
796
        continue;
797
      }
798

    
799
      if ($bit[0] == '%') {
800
        // Chop off that %.
801
        $name = substr($bit, 1);
802

    
803
        // Check to see if the argument plugin allows to arg:
804
        if (!empty($page->arguments[$name])) {
805
          ctools_include('context');
806
          $plugin = ctools_get_argument($page->arguments[$name]['name']);
807
          if (!empty($plugin['path placeholder to_arg'])) {
808
            continue;
809
          }
810
        }
811

    
812
        form_error($form['menu']['type'], t('Paths with non optional placeholders cannot be used as normal menu items unless the selected argument handler provides a default argument to use for the menu item.'));
813
        return;
814
      }
815
    }
816
  }
817
}
818

    
819
/**
820
 * Submit handler for the menu form for add/edit page task.
821
 */
822
function page_manager_page_form_menu_submit(&$form, &$form_state) {
823
  $form_state['page']->subtask['subtask']->menu = $form_state['values']['menu'];
824
  $form_state['page']->path_changed = TRUE;
825
}
826

    
827
/**
828
 * Form to handle menu item controls.
829
 */
830
function page_manager_page_form_access($form, &$form_state) {
831
  ctools_include('context');
832
  $form_state['module'] = 'page_manager_page';
833
  $form_state['callback argument'] = $form_state['page']->task_name;
834
  $form_state['access'] = $form_state['page']->subtask['subtask']->access;
835
  $form_state['no buttons'] = TRUE;
836
  $form_state['contexts'] = array();
837

    
838
  // Load contexts based on argument data:
839
  if ($arguments = _page_manager_page_get_arguments($form_state['page']->subtask['subtask'])) {
840
    $form_state['contexts'] = ctools_context_get_placeholders_from_argument($arguments);
841
  }
842

    
843
  ctools_include('context-access-admin');
844
  $form = ctools_access_admin_form($form, $form_state);
845

    
846
  return $form;
847
}
848

    
849
/**
850
 * Submit handler to deal with access control changes.
851
 */
852
function page_manager_page_form_access_submit(&$form, &$form_state) {
853
  $form_state['page']->subtask['subtask']->access['logic'] = $form_state['values']['logic'];
854
  $form_state['page']->path_changed = TRUE;
855
}
856

    
857
/**
858
 * Form to handle assigning argument handlers to named arguments.
859
 */
860
function page_manager_page_form_argument($form, &$form_state) {
861
  $page = &$form_state['page']->subtask['subtask'];
862
  $path = $page->path;
863

    
864
  $arguments = page_manager_page_get_named_arguments($path);
865

    
866
  $form['table'] = array(
867
    '#theme' => 'page_manager_page_form_argument_table',
868
    '#page-manager-path' => $path,
869
    'argument' => array(),
870
  );
871

    
872
  $task_name = $form_state['page']->task_name;
873
  foreach ($arguments as $keyword => $position) {
874
    $conf = array();
875

    
876
    if (isset($page->temporary_arguments[$keyword]) && !empty($form_state['allow temp'])) {
877
      $conf = $page->temporary_arguments[$keyword];
878
    }
879
    elseif (isset($page->arguments[$keyword])) {
880
      $conf = $page->arguments[$keyword];
881
    }
882

    
883
    $context = t('No context assigned');
884

    
885
    $plugin = array();
886
    if ($conf && isset($conf['name'])) {
887
      ctools_include('context');
888
      $plugin = ctools_get_argument($conf['name']);
889

    
890
      if (isset($plugin['title'])) {
891
        $context = $plugin['title'];
892
      }
893
    }
894

    
895
    $form['table']['argument'][$keyword]['#keyword'] = $keyword;
896
    $form['table']['argument'][$keyword]['#position'] = $position;
897
    $form['table']['argument'][$keyword]['#context'] = $context;
898

    
899
    // The URL for this ajax button.
900
    $form['table']['argument'][$keyword]['change-url'] = array(
901
      '#attributes' => array('class' => array("page-manager-context-$keyword-change-url")),
902
      '#type' => 'hidden',
903
      '#value' => url("admin/structure/pages/argument/change/$task_name/$keyword", array('absolute' => TRUE)),
904
    );
905
    $form['table']['argument'][$keyword]['change'] = array(
906
      '#type' => 'submit',
907
      '#value' => t('Change'),
908
      '#attributes' => array('class' => array('ctools-use-modal')),
909
      '#id' => "page-manager-context-$keyword-change",
910
    );
911

    
912
    $form['table']['argument'][$keyword]['settings'] = array();
913

    
914
    // Only show the button if this has a settings form available:
915
    if (!empty($plugin)) {
916
      // The URL for this ajax button.
917
      $form['table']['argument'][$keyword]['settings-url'] = array(
918
        '#attributes' => array('class' => array("page-manager-context-$keyword-settings-url")),
919
        '#type' => 'hidden',
920
        '#value' => url("admin/structure/pages/argument/settings/$task_name/$keyword", array('absolute' => TRUE)),
921
      );
922
      $form['table']['argument'][$keyword]['settings'] = array(
923
        '#type' => 'submit',
924
        '#value' => t('Settings'),
925
        '#attributes' => array('class' => array('ctools-use-modal')),
926
        '#id' => "page-manager-context-$keyword-settings",
927
      );
928
    }
929
  }
930

    
931
  return $form;
932
}
933

    
934
/**
935
 * Theme the table for this form.
936
 */
937
function theme_page_manager_page_form_argument_table($vars) {
938
  $form = $vars['form'];
939
  $header = array(
940
    array('data' => t('Argument'), 'class' => array('page-manager-argument')),
941
    array('data' => t('Position in path'), 'class' => array('page-manager-position')),
942
    array('data' => t('Context assigned'), 'class' => array('page-manager-context')),
943
    array('data' => t('Operations'), 'class' => array('page-manager-operations')),
944
  );
945

    
946
  $rows = array();
947

    
948
  ctools_include('modal');
949
  ctools_modal_add_js();
950
  foreach (element_children($form['argument']) as $key) {
951
    $row = array();
952
    $row[] = '%' . check_plain($form['argument'][$key]['#keyword']);
953
    $row[] = check_plain($form['argument'][$key]['#position']);
954
    $row[] = $form['argument'][$key]['#context'] . ' &nbsp; ' . drupal_render($form['argument'][$key]['change']);;
955
    $row[] = drupal_render($form['argument'][$key]['settings']) . drupal_render($form['argument'][$key]);
956

    
957
    $rows[] = array('data' => $row);
958
  }
959

    
960
  if (!$rows) {
961
    $rows[] = array(array('data' => t('The path %path has no arguments to configure.', array('%path' => $form['#page-manager-path'])), 'colspan' => 4));
962
  }
963

    
964
  $attributes = array(
965
    'id' => 'page-manager-argument-table',
966
  );
967

    
968
  $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => $attributes));
969
  return $output;
970
}
971

    
972
/**
973
 * Ajax entry point to edit an item.
974
 */
975
function page_manager_page_subtask_argument_ajax($step = NULL, $task_name = NULL, $keyword = NULL) {
976
  ctools_include('ajax');
977
  ctools_include('modal');
978
  ctools_include('context');
979
  ctools_include('wizard');
980

    
981
  if (!$step) {
982
    return ctools_ajax_render_error();
983
  }
984

    
985
  if (!$cache = page_manager_get_page_cache($task_name)) {
986
    return ctools_ajax_render_error(t('Invalid object name.'));
987
  }
988

    
989
  $page = &$cache->subtask['subtask'];
990
  $path = $page->path;
991
  $arguments = page_manager_page_get_named_arguments($path);
992

    
993
  // Load stored object from cache.
994
  if (!isset($arguments[$keyword])) {
995
    return ctools_ajax_render_error(t('Invalid keyword.'));
996
  }
997

    
998
  // Set up wizard info.
999
  $form_info = array(
1000
    'id' => 'page_manager_page_argument',
1001
    'path' => "admin/structure/pages/argument/%step/$task_name/$keyword",
1002
    'show cancel' => TRUE,
1003
    'next callback' => 'page_manager_page_argument_next',
1004
    'finish callback' => 'page_manager_page_argument_finish',
1005
    'cancel callback' => 'page_manager_page_argument_cancel',
1006
    'order' => array(
1007
      'change' => t('Change context type'),
1008
      'settings' => t('Argument settings'),
1009
    ),
1010
    'forms' => array(
1011
      'change' => array(
1012
        'title' => t('Change argument'),
1013
        'form id' => 'page_manager_page_argument_form_change',
1014
      ),
1015
      'settings' => array(
1016
        'title' => t('Argument settings'),
1017
        'form id' => 'page_manager_page_argument_form_settings',
1018
      ),
1019
    ),
1020
  );
1021

    
1022
  $form_state = array(
1023
    'page' => $cache,
1024
    'keyword' => $keyword,
1025
    'ajax' => TRUE,
1026
    'modal' => TRUE,
1027
    'modal return' => TRUE,
1028
    'commands' => array(),
1029
  );
1030

    
1031
  $output = ctools_wizard_multistep_form($form_info, $step, $form_state);
1032
  if (!empty($form_state['cancel'])) {
1033
    $commands = array(ctools_modal_command_dismiss());
1034
  }
1035
  elseif (!empty($form_state['complete'])) {
1036
    if (isset($page->temporary_arguments[$keyword])) {
1037
      $page->arguments[$keyword] = $page->temporary_arguments[$keyword];
1038
    }
1039

    
1040
    if (isset($page->temporary_arguments)) {
1041
      unset($page->temporary_arguments);
1042
    }
1043

    
1044
    // Update the cache with changes.
1045
    page_manager_set_page_cache($cache);
1046

    
1047
    // Rerender the table so we can ajax it back in.
1048
    // Go directly to the form and retrieve it using a blank form and
1049
    // a clone of our current form state. This is an abbreviated
1050
    // drupal_get_form that is halted prior to render and is never
1051
    // fully processed, but is guaranteed to produce the same form we
1052
    // started with so we don't have to do crazy stuff to rerender
1053
    // just part of it.
1054
    // @todo should there be a tool to do this?
1055

    
1056
    $clone_state = $form_state;
1057
    $clone_state['allow temp'] = TRUE;
1058
    $form = drupal_build_form('page_manager_page_form_argument', $form_state);
1059

    
1060
    // Render just the table portion.
1061
    $output = drupal_render($form['table']);
1062
    $commands = array(
1063
      ajax_command_replace('#page-manager-argument-table', $output),
1064
      ctools_modal_command_dismiss(),
1065
    );
1066
  }
1067
  else {
1068
    $commands = ctools_modal_form_render($form_state, $output);
1069
  }
1070
  print ajax_render($commands);
1071
  ajax_footer();
1072
  exit;
1073
}
1074

    
1075
/**
1076
 * Callback generated when the add page process is finished.
1077
 */
1078
function page_manager_page_argument_finish(&$form_state) {
1079
}
1080

    
1081
/**
1082
 * Callback generated when the 'next' button is clicked.
1083
 *
1084
 * All we do here is store the cache.
1085
 */
1086
function page_manager_page_argument_next(&$form_state) {
1087
  // Update the cache with changes.
1088
  page_manager_set_page_cache($form_state['page']);
1089
}
1090

    
1091
/**
1092
 * Callback generated when the 'cancel' button is clicked.
1093
 *
1094
 * We might have some temporary data lying around. We must remove it.
1095
 */
1096
function page_manager_page_argument_cancel(&$form_state) {
1097
  $page = &$form_state['page']->subtask['subtask'];
1098
  if (isset($page->temporary_arguments)) {
1099
    unset($page->temporary_arguments);
1100
    // Update the cache with changes.
1101
    page_manager_set_page_cache($page);
1102
  }
1103
}
1104

    
1105
/**
1106
 * Basic settings form for a page manager page.
1107
 */
1108
function page_manager_page_argument_form_change($form, &$form_state) {
1109
  $page = &$form_state['page']->subtask['subtask'];
1110
  $keyword = &$form_state['keyword'];
1111

    
1112
  ctools_include('context');
1113
  $plugins = ctools_get_arguments();
1114

    
1115
  $options = array();
1116
  foreach ($plugins as $id => $plugin) {
1117
    if (empty($plugin['no ui'])) {
1118
      $options[$id] = $plugin['title'];
1119
    }
1120
  }
1121

    
1122
  asort($options);
1123

    
1124
  $options = array('' => t('No context selected')) + $options;
1125

    
1126
  $argument = '';
1127
  if (isset($page->arguments[$keyword]) && isset($page->arguments[$keyword]['name'])) {
1128
    $argument = $page->arguments[$keyword]['name'];
1129
  }
1130

    
1131
  $form['argument'] = array(
1132
    '#type' => 'radios',
1133
    '#options' => $options,
1134
    '#default_value' => $argument,
1135
  );
1136

    
1137
  return $form;
1138
}
1139

    
1140
/**
1141
 * Submit handler to change an argument.
1142
 */
1143
function page_manager_page_argument_form_change_submit(&$form, &$form_state) {
1144
  $page     = &$form_state['page']->subtask['subtask'];
1145
  $keyword  = &$form_state['keyword'];
1146
  $argument = $form_state['values']['argument'];
1147

    
1148
  // If the argument is not changing, we do not need to do anything.
1149
  if (isset($page->arguments[$keyword]['name']) && $page->arguments[$keyword]['name'] == $argument) {
1150
    // Set the task to cancel since no change means do nothing:
1151
    $form_state['clicked_button']['#wizard type'] = 'cancel';
1152
    return;
1153
  }
1154

    
1155
  ctools_include('context');
1156

    
1157
  // If switching to the no context, just wipe out the old data.
1158
  if (empty($argument)) {
1159
    $form_state['clicked_button']['#wizard type'] = 'finish';
1160
    $page->temporary_arguments[$keyword] = array(
1161
      'settings' => array(),
1162
      'identifier' => t('No context'),
1163
    );
1164
    return;
1165
  }
1166

    
1167
  $plugin = ctools_get_argument($argument);
1168

    
1169
  // Acquire defaults.
1170
  $settings = array();
1171

    
1172
  if (isset($plugin['default'])) {
1173
    if (is_array($plugin['default'])) {
1174
      $settings = $plugin['default'];
1175
    }
1176
    elseif (function_exists($plugin['default'])) {
1177
      $settings = $plugin['default']();
1178
    }
1179
  }
1180

    
1181
  $id = ctools_context_next_id($page->arguments, $argument);
1182
  $title = isset($plugin['title']) ? $plugin['title'] : t('No context');
1183

    
1184
  // Set the new argument in a temporary location.
1185
  $page->temporary_arguments[$keyword] = array(
1186
    'id' => $id,
1187
    'identifier' => $title . ($id > 1 ? ' ' . $id : ''),
1188
    'name' => $argument,
1189
    'settings' => $settings,
1190
  );
1191
}
1192

    
1193
/**
1194
 * Basic settings form for a page manager page.
1195
 */
1196
function page_manager_page_argument_form_settings($form, &$form_state) {
1197
  $page = &$form_state['page']->subtask['subtask'];
1198
  $keyword = &$form_state['keyword'];
1199

    
1200
  if (isset($page->temporary_arguments[$keyword])) {
1201
    $conf = $page->temporary_arguments[$keyword];
1202
  }
1203
  elseif (isset($page->arguments[$keyword])) {
1204
    $conf = $page->temporary_arguments[$keyword] = $page->arguments[$keyword];
1205
  }
1206

    
1207
  if (!isset($conf)) {
1208
    // This should be impossible and thus never seen.
1209
    $form['error'] = array('#value' => t('Error: missing argument.'));
1210
    return;
1211
  }
1212

    
1213
  ctools_include('context');
1214
  $plugin = ctools_get_argument($conf['name']);
1215

    
1216
  $form['settings'] = array(
1217
    '#tree' => TRUE,
1218
  );
1219

    
1220
  $form['identifier'] = array(
1221
    '#type' => 'textfield',
1222
    '#title' => t('Context identifier'),
1223
    '#description' => t('This is the title of the context used to identify it later in the administrative process. This will never be shown to a user.'),
1224
    '#default_value' => $conf['identifier'],
1225
  );
1226

    
1227
  if (!$plugin) {
1228
    // This should be impossible and thus never seen.
1229
    $form['error'] = array('#value' => t('Error: missing or invalid argument plugin %argument.', array('%argument', $argument)));
1230
    return;
1231
  }
1232

    
1233
  if ($function = ctools_plugin_get_function($plugin, 'settings form')) {
1234
    $function($form, $form_state, $conf['settings']);
1235
  }
1236

    
1237
  $form_state['plugin'] = $plugin;
1238
  return $form;
1239
}
1240

    
1241
/**
1242
 * Validate handler for argument settings.
1243
 */
1244
function page_manager_page_argument_form_settings_validate(&$form, &$form_state) {
1245
  if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form validate')) {
1246
    $function($form, $form_state);
1247
  }
1248
}
1249

    
1250
/**
1251
 * Submit handler for argument settings.
1252
 */
1253
function page_manager_page_argument_form_settings_submit(&$form, &$form_state) {
1254
  if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form submit')) {
1255
    $function($form, $form_state);
1256
  }
1257

    
1258
  $page = &$form_state['page']->subtask['subtask'];
1259
  $keyword = &$form_state['keyword'];
1260
  // Copy the form to our temporary location which will get moved again when
1261
  // finished. Yes, finished is always next but finish can happen from other
1262
  // locations so we funnel through that path rather than duplicate.
1263
  $page->temporary_arguments[$keyword]['identifier'] = $form_state['values']['identifier'];
1264
  if (isset($form_state['values']['settings'])) {
1265
    $page->temporary_arguments[$keyword]['settings'] = $form_state['values']['settings'];
1266
  }
1267
  else {
1268
    $page->temporary_arguments[$keyword]['settings'] = array();
1269
  }
1270
}
1271

    
1272
/**
1273
 * Import a task handler from cut & paste.
1274
 */
1275
function page_manager_page_import_subtask($form, &$form_state, $task_name) {
1276
  $form_state['task'] = page_manager_get_task($task_name);
1277

    
1278
  drupal_set_title(t('Import page'));
1279
  $form['name'] = array(
1280
    '#type' => 'textfield',
1281
    '#title' => t('Page name'),
1282
    '#description' => t('Enter the name to use for this page if it is different from the source page. Leave blank to use the original name of the page.'),
1283
  );
1284

    
1285
  $form['path'] = array(
1286
    '#type' => 'textfield',
1287
    '#title' => t('Path'),
1288
    '#description' => t('Enter the path to use for this page if it is different from the source page. Leave blank to use the original path of the page.'),
1289
  );
1290

    
1291
  $form['overwrite'] = array(
1292
    '#type' => 'checkbox',
1293
    '#title' => t('Allow overwrite of an existing page'),
1294
    '#description' => t('If the name you selected already exists in the database, this page will be allowed to overwrite the existing page.'),
1295
  );
1296

    
1297
  $form['object'] = array(
1298
    '#type' => 'textarea',
1299
    '#title' => t('Paste page code here'),
1300
    '#rows' => 15,
1301
  );
1302

    
1303
  $form['submit'] = array(
1304
    '#type' => 'submit',
1305
    '#value' => t('Import'),
1306
  );
1307
  return $form;
1308
}
1309

    
1310
/**
1311
 * Ensure we got a valid page.
1312
 */
1313
function page_manager_page_import_subtask_validate(&$form, &$form_state) {
1314
  ob_start();
1315
  eval($form_state['values']['object']);
1316
  ob_end_clean();
1317

    
1318
  if (!isset($page) || !is_object($page)) {
1319
    $errors = ob_get_contents();
1320
    if (empty($errors)) {
1321
      $errors = t('No handler found.');
1322
    }
1323
    form_error($form['object'], t('Unable to get a page from the import. Errors reported: @errors', array('@errors' => $errors)));
1324
  }
1325

    
1326
  if (empty($form_state['values']['name'])) {
1327
    $form_state['values']['name'] = $page->name;
1328
  }
1329

    
1330
  $task_name = page_manager_make_task_name('page', $form_state['values']['name']);
1331
  $form_state['cache'] = page_manager_get_page_cache($task_name);
1332

    
1333
  if ($form_state['cache'] && $form_state['cache']->locked) {
1334
    form_error($form['name'], t('That page name is in use and locked by another user. You must <a href="!break">break the lock</a> on that page before proceeding, or choose a different name.', array('!break' => url(page_manager_edit_url($task_name, array('actions', 'break-lock'))))));
1335
    return;
1336
  }
1337

    
1338
  if (empty($form_state['values']['path'])) {
1339
    $form_state['values']['path'] = $page->path;
1340
  }
1341

    
1342
  if (empty($form_state['values']['overwrite'])) {
1343
    $page->name = NULL;
1344
  }
1345

    
1346
  $form_state['page'] = new stdClass();
1347
  $form_state['page']->subtask['subtask'] = $page;
1348
  page_manager_page_form_basic_validate($form, $form_state);
1349
}
1350

    
1351
/**
1352
 * Submit the import page to create the new page and redirect.
1353
 */
1354
function page_manager_page_import_subtask_submit($form, &$form_state) {
1355
  $page = &$form_state['page']->subtask['subtask'];
1356
  $page->name = $form_state['values']['name'];
1357
  $page->path = $form_state['values']['path'];
1358

    
1359
  $task_name = page_manager_make_task_name('page', $page->name);
1360
  $cache = page_manager_get_page_cache($task_name);
1361
  if (!$cache) {
1362
    $cache = new stdClass();
1363
  }
1364

    
1365
  page_manager_page_new_page_cache($page, $cache);
1366
  page_manager_set_page_cache($cache);
1367

    
1368
  $form_state['redirect'] = page_manager_edit_url($task_name);
1369
}
1370

    
1371
/**
1372
 * Entry point to export a page.
1373
 */
1374
function page_manager_page_form_export($form, &$form_state) {
1375
  $page = $form_state['page']->subtask['subtask'];
1376

    
1377
  $export = page_manager_page_export($page, $form_state['page']->handlers);
1378

    
1379
  $lines = substr_count($export, "\n");
1380
  $form['code'] = array(
1381
    '#type' => 'textarea',
1382
    '#default_value' => $export,
1383
    '#rows' => $lines,
1384
  );
1385

    
1386
  unset($form['buttons']);
1387
  return $form;
1388
}
1389

    
1390
/**
1391
 * Entry point to clone a page.
1392
 */
1393
function page_manager_page_form_clone($form, &$form_state) {
1394
  $page = &$form_state['page']->subtask['subtask'];
1395

    
1396
  // This provides its own button because it does something totally different.
1397
  unset($form['buttons']);
1398

    
1399
  $form['admin_title'] = array(
1400
    '#type' => 'textfield',
1401
    '#title' => t('Administrative title'),
1402
    '#description' => t('The name of this page. This will appear in the administrative interface to easily identify it.'),
1403
    '#default_value' => $page->admin_title,
1404
  );
1405

    
1406
  $form['name'] = array(
1407
    '#type' => 'machine_name',
1408
    '#title' => t('Page name'),
1409
    '#machine_name' => array(
1410
      'exists' => 'page_manager_page_load',
1411
      'source' => array('admin_title'),
1412
    ),
1413
    '#description' => t('Enter the name to the new page It must be unique and contain only alphanumeric characters and underscores.'),
1414
  );
1415

    
1416
  // Path.
1417
  $form['path'] = array(
1418
    '#type' => 'textfield',
1419
    '#title' => t('Path'),
1420
    '#description' => t('The URL path to get to this page. You may create named placeholders for variable parts of the path by using %name for required elements and !name for optional elements. For example: "node/%node/foo", "forum/%forum" or "dashboard/!input". These named placeholders can be turned into contexts on the arguments form. You cannot use the same path as the original page.'),
1421
    '#default_value' => $page->path,
1422
  );
1423

    
1424
  $form['handlers'] = array(
1425
    '#type' => 'checkbox',
1426
    '#title' => t('Clone variants'),
1427
    '#description' => t('If checked all variants associated with the page will be cloned as well. If not checked the page will be cloned without variants.'),
1428
    '#default_value' => TRUE,
1429
  );
1430

    
1431
  $form['submit'] = array(
1432
    '#type' => 'submit',
1433
    '#value' => t('Clone'),
1434
  );
1435

    
1436
  return $form;
1437
}
1438

    
1439
/**
1440
 * Validate clone page form.
1441
 */
1442
function page_manager_page_form_clone_validate(&$form, &$form_state) {
1443
  $page = &$form_state['page']->subtask['subtask'];
1444

    
1445
  $page->old_name = $page->name;
1446
  $page->name = NULL;
1447
  page_manager_page_form_basic_validate($form, $form_state);
1448
}
1449

    
1450
/**
1451
 * Submit clone page form.
1452
 *
1453
 * Load the page, change the name(s) to protect the innocent, and if
1454
 * requested, load all the task handlers so that they get saved properly too.
1455
 */
1456
function page_manager_page_form_clone_submit(&$form, &$form_state) {
1457
  $original = $form_state['page']->subtask['subtask'];
1458

    
1459
  $original->name = $form_state['values']['name'];
1460
  $original->admin_title = $form_state['values']['admin_title'];
1461
  $original->path = $form_state['values']['path'];
1462

    
1463
  $handlers = !empty($form_state['values']['handlers']) ? $form_state['page']->handlers : FALSE;
1464
  // Ensure the handler uuids are re-generated.
1465
  if ($handlers) {
1466
    foreach ($handlers as &$handler) {
1467
      if (isset($handler->conf['display']) && method_exists($handler->conf['display'], 'clone_display')) {
1468
        $handler->conf['display'] = $handler->conf['display']->clone_display();
1469
      }
1470
    }
1471
  }
1472

    
1473
  // Export the handler, which is a fantastic way to clean database IDs out of it.
1474
  $export = page_manager_page_export($original, $handlers);
1475
  ob_start();
1476
  eval($export);
1477
  ob_end_clean();
1478

    
1479
  $task_name = page_manager_make_task_name('page', $page->name);
1480
  $cache = new stdClass();
1481

    
1482
  page_manager_page_new_page_cache($page, $cache);
1483
  page_manager_set_page_cache($cache);
1484

    
1485
  $form_state['redirect'] = page_manager_edit_url($task_name);
1486
}
1487

    
1488
/**
1489
 * Entry point to export a page.
1490
 */
1491
function page_manager_page_form_delete($form, &$form_state) {
1492
  $page = &$form_state['page']->subtask['subtask'];
1493

    
1494
  if ($page->type == t('Overridden')) {
1495
    $text = t('Reverting the page will delete the page that is in the database, reverting it to the original default page. Any changes you have made will be lost and cannot be recovered.');
1496
  }
1497
  else {
1498
    $text = t('Are you sure you want to delete this page? Deleting a page cannot be undone.');
1499
  }
1500
  $form['markup'] = array(
1501
    '#value' => '<p>' . $text . '</p>',
1502
  );
1503

    
1504
  if (empty($form_state['page']->locked)) {
1505
    unset($form['buttons']);
1506
    $form['delete'] = array(
1507
      '#type' => 'submit',
1508
      '#value' => $page->type == t('Overridden') ? t('Revert') : t('Delete'),
1509
    );
1510
  }
1511

    
1512
  return $form;
1513
}
1514

    
1515
/**
1516
 * Submit handler to delete a view.
1517
 */
1518
function page_manager_page_form_delete_submit(&$form, &$form_state) {
1519
  $page = $form_state['page']->subtask['subtask'];
1520
  page_manager_page_delete($page);
1521
  if ($page->type != t('Overridden')) {
1522
    $form_state['redirect'] = 'admin/structure/pages';
1523
    drupal_set_message(t('The page has been deleted.'));
1524
  }
1525
  else {
1526
    $form_state['redirect'] = page_manager_edit_url($form_state['page']->task_name, array('summary'));
1527
    drupal_set_message(t('The page has been reverted.'));
1528
  }
1529
}