Security update for permissions_by_term
[yaffs-website] / web / modules / custom / menu_views / menu_views.admin.inc
1 <?php
2
3
4
5 /**
6  * @file
7  * Form hooks for the menu_views module.
8  */
9
10 /**
11  * Implements hook_form_FORM_ID_alter().
12  *
13  * Appends the attached view to the title of the menu item.
14  */
15 function menu_views_form_menu_overview_form_alter(&$form, &$form_state) {
16   $attached = FALSE;
17   $elements = \Drupal\Core\Render\Element::children($form);
18   foreach ($elements as $mlid) {
19     $element = &$form[$mlid];
20     // Only process menu items
21     if (isset($element['#item'])) {
22       $menu_item = &$element['#item'];
23       // Only change the title for attached views
24       $item = _menu_views_get_item($menu_item);
25       _menu_views_tokenize($item, TRUE);
26       
27       if ($item['type'] == 'view' && $item['view']['name'] && $item['view']['display']) {
28         if (!$attached) {
29           $form['#attached']['css'][] = drupal_get_path('module', 'menu_views') . '/menu_views.admin.css';
30           $attached = TRUE;
31         }
32         $title = '';
33         if ($view = views_get_view($item['view']['name'])) {
34           if ($view->access($item['view']['display']) && $view->set_display($item['view']['display'])) {
35             $view->set_arguments(explode('/', $item['view']['arguments']));
36             // Provide title options for the view.
37             $title = \Drupal\Component\Utility\Xss::filterAdmin($item['view']['settings']['title_override']);
38             if (empty($title)) {
39               $title = \Drupal\Component\Utility\Xss::filterAdmin($view->get_title());
40             }
41           }
42           $view->destroy();
43         }
44         if (empty($title)) {
45           $title = t($item['view']['name']) . '-' . t($item['view']['display']);
46         }
47         $element['title'] = array(
48           '#prefix' => '<div class="view" title="View: ' . $item['view']['name'] . '-' . $item['view']['display'] . '">',
49           '#suffix' => '</div>',
50           '#markup' => '<strong>View:</strong> ' . $title . ($menu_item['hidden'] ? ' (' . t('disabled') . ')' : ''),
51         );
52       }
53     }
54   }
55 }
56
57
58 /**
59  * Implements hook_form_FORM_ID_alter().
60  *
61  * Adds menu views options to the menu edit item form.
62  *
63  * @see _menu_views_form_alter()
64  */
65 function menu_views_form_menu_link_edit_alter(&$form, &$form_state, $form_id) {
66   // @FIXME
67 // drupal_set_title() has been removed. There are now a few ways to set the title
68 // dynamically, depending on the situation.
69 // 
70 // 
71 // @see https://www.drupal.org/node/2067859
72 // drupal_set_title(t('Edit menu item'));
73 // Moved into form_alter - jeff
74
75
76   _menu_views_form_alter($form, $form, $form_state, $form_id);
77 }
78
79 /**
80  * Implements hook_form_FORM_ID_alter().
81  *
82  * Adds menu views options to the node's edit menu item form.
83  *
84  * @see _menu_views_form_alter()
85  */
86 function menu_views_form_node_form_alter(&$form, &$form_state, $form_id) {
87   if (isset($form['menu']['link'])) {
88     _menu_views_form_alter($form['menu']['link'], $form, $form_state, $form_id);
89   }
90 }
91
92 /**
93  * Helper function to determine where form values for menu views are located.
94  *
95  * @return
96  *  Array of parents to the menu views form elements.
97  */
98 function _menu_views_form_parents($form) {
99   $parents = array();
100   if (isset($form['#node'])) {
101     $parents[] = 'menu';
102     $parents[] = 'options';
103   }
104   elseif (_menu_views_options_tree($form)) {
105     $parents[] = 'options';
106   }
107   $parents[] = 'menu_views';
108   $parents[] = 'view';
109   return $parents;
110 }
111
112 /**
113  * Helper function that inserts a fieldset containing available replacement tokens.
114  *
115  * @see _menu_views_form()
116  */
117 function _menu_views_form_tokens_ui(array &$element) {
118   static $enabled;
119   if (!isset($enabled)) {
120     $enabled = \Drupal::moduleHandler()->moduleExists('token'); 
121   }
122   if ($enabled) {
123     $i = 0;
124     while (isset($element['tokens_' . $i])) {
125       $i++;
126     }
127     $element['tokens_' . $i] = array(
128       '#type' => 'container',
129     );
130     $element['tokens_' . $i]['tokens'] = array(
131       '#theme' => 'token_tree',
132       '#token_types' => array('menu-link'),
133       '#dialog' => TRUE,
134     );
135   }
136 }
137
138 /**
139  * Alters existing forms in preparation for adding Menu Views to it.
140  *
141  * @param $element
142  *   The top level menu item edit form element passed by reference.
143  * @param $form
144  *   The complete form array passed by reference.
145  * @param $form_state
146  *   The complete form state array passed by reference.
147  */
148 function _menu_views_form_alter(array &$element, array &$form, array &$form_state, $form_id) {
149   // Still need to render the form, just hide it for those who don't have access.
150   $access = \Drupal::currentUser()->hasPermission('administer menu views');
151   // Only need to attach or alter form if user has access.
152   if ($access) {
153     $form['#title'] = t('Edit menu item');
154
155     // Unset the previous values so that the new values can get saved.
156     if (isset($element['options']['#value']['menu_views'])) {
157       unset($element['options']['#value']['menu_views']);
158     }
159     $module_path = drupal_get_path('module', 'menu_views');
160     // Attach CSS.
161     $element['#attached']['css'][] = array(
162       'data' => $module_path . '/menu_views.admin.css',
163       'type' => 'file',
164       'group' => CSS_THEME,
165       'weight' => 100
166     );
167     // Attach JavaScript.
168     // @FIXME
169 // // @FIXME
170 // // This looks like another module's variable. You'll need to rewrite this call
171 // // to ensure that it uses the correct configuration object.
172 // $element['#attached']['js'][] = array(
173 //       'data' => array('menu_views' => array(
174 //         'admin_theme' => variable_get('admin_theme', 'bartik'),
175 //         'node_form' => isset($form['#node']),
176 //       )),
177 //       'type' => 'setting',
178 //     );
179
180     $element['#attached']['js'][] = array(
181       'data' => $module_path . '/menu_views.admin.js',
182       'type' => 'file',
183       'group' => JS_THEME,
184       'weight' => 100,
185     );
186     // Create AJAX wrapper around the menu edit form element.
187     $element['#prefix'] = '<div id="menu-edit-item-wrapper">';
188     $element['#suffix'] = '</div>';
189   }
190     
191   // Get values for the new menu views item, existing menu views item or submitted form values.
192   $item = _menu_views_get_item($form, $form_state);
193   // Use the loaded node if it exists.
194   $node = isset($form['#node']) ? $form['#node'] : FALSE;
195   
196   // Get the original menu link, if it exists.
197   $menu_link = array();
198   if (isset($form['original_item']['#value'])) {
199     $menu_link = $form['original_item']['#value'];
200   }
201   elseif ($node && isset($node->menu)) {
202     $menu_link = $node->menu;
203   }
204   
205   // Determine which menu item type is visible.
206   $visible = !('view' === $item['type']);
207   
208   // Determine the correct link path to show or set values for.
209   if (isset($element['link_path'])) {
210     if ('link' === $item['type'] && !empty($element['link_path']['#default_value']) && '<view>' === $element['link_path']['#default_value']) {
211       $element['link_path']['#default_value'] = $item['original_path'];
212     }
213     elseif ('view' === $item['type']) {
214       if (!empty($element['link_path']['#default_value']) && '<view>' !== $element['link_path']['#default_value']) {
215         $item['original_path'] = $element['link_path']['#default_value'];
216       }
217       $element['link_path']['#default_value'] = '<view>';
218     }
219   }
220   elseif ($node) {
221     if ('view' === $item['type']) {
222       $element['link_path'] = array(
223         '#type' => 'value',
224         '#value' => '<view>',
225       );
226     }
227     else {
228       $element['link_path'] = array(
229         '#type' => 'value',
230         '#value' => $node && isset($node->nid) ? 'node/' . $node->nid : '',
231       );
232     }
233   }
234   
235   // If the original path is empty and this is a node, use the node path.
236   if (empty($item['original_path']) && $node && isset($node->nid) && $node->nid) {
237     $item['original_path'] = 'node/' . $node->nid;
238   }
239   
240   // If this menu item is a view and user does not have permissions to administer menu views, restrict access to the form.
241   // Cannot use drupal_access_denied() because this form can also be inside a node edit form.
242   if ($item['type'] == 'view' && !$access) {
243     $element['disabled'] = array(
244       '#prefix' => '<div class="messages error">',
245       '#suffix' => '</div>',
246       '#markup' => t('You do not have access to edit this type of menu item.'),
247       '#weight' => -9999,
248     );
249     $visible = FALSE;
250     // Hide the action buttons on menu item edit forms.
251     if (isset($element['actions'])) {
252       $element['actions']['#access'] = $access;
253     }
254     // Hide the checkbox toggle on node edit forms.
255     if (isset($form['menu']['enabled'])) {
256       $form['menu']['enabled']['#access'] = $access;
257     }
258   }
259   
260   // Replace Parent Menu Options
261   $options = _menu_views_parent_options(menu_get_menus(), $menu_link);
262   if ($node && isset($node->type)) {
263     $options = _menu_views_parent_options(menu_get_menus(), $menu_link['mlid'] ? $menu_link : $node->type, $node->type);
264   }
265   $element['parent']['#title'] = t('Parent Item');
266   $element['parent']['#options'] = $options;
267
268   // Move general menu item settings into a container.
269   if ($access) {
270     $element['menu_item_settings'] = array(
271       '#access' => $access,
272       '#type' => 'fieldset',
273       '#title' => t('Menu item settings'),
274       '#parents' => isset($form['#node']) ? array('menu') : array(),
275       '#weight' => $item['type'] == 'view' ? 50 : 1,
276       '#attributes' => array('id' => 'menu_item_settings', 'class' => array('menu-item-settings')),
277     );
278     if (isset($element['enabled'])) {
279       $element['menu_item_settings']['enabled'] = $element['enabled'];
280       unset($element['enabled']);
281     }
282     $element['menu_item_settings']['expanded'] = $element['expanded'];
283     unset($element['expanded']);
284     $element['menu_item_settings']['parent'] = $element['parent'];
285     unset($element['parent']);
286     $element['menu_item_settings']['weight'] = $element['weight'];
287     unset($element['weight']);
288   }
289
290   // Add support for the xmlsitemap_menu module.
291   if (\Drupal::moduleHandler()->moduleExists('xmlsitemap_menu')) {
292     $element['xmlsitemap']['#weight'] = $item['type'] === 'view' ? 51 : 30;
293   }
294
295   // Create a radio toggle for menu item types: link or view.
296   $element['menu_item_type'] = array(
297     '#access' => $access,
298     '#type' => 'radios',
299     '#title' => t('Menu item type'),
300     '#options' => array('link' => t('Link'), 'view' => t('View')),
301     '#default_value' => $item['type'],
302     // Add container-inline style for admin themes like Rubik.
303     '#prefix' => '<div id="menu-item-type" class="form-item container-inline">',
304     '#suffix' => '</div>',
305     '#ajax' => array(
306       'callback' => '_menu_views_form_ajax',
307       'wrapper' => 'menu-edit-item-wrapper',
308     ),
309     // Ensure this is rendered at the top of the form.
310     '#weight' => -1000,
311   );
312   
313   // Determine if menu_attributes is enabled.
314   $menu_attributes = \Drupal::moduleHandler()->moduleExists('menu_attributes');
315
316   // Show/Hide the core link form elements based on menu item type of: link or view.
317   foreach (\Drupal\Core\Render\Element::children($element) as $child) {
318     // Skip options (handled below) and actions.
319     $type = isset($element[$child]['#type']) ? $element[$child]['#type'] : '';
320
321     // Ensure necessary children are always present (regardless of their type).
322     $ignore_children = array(
323       'menu_item_type', 'disabled', 'menu_item_settings',
324       'form_build_id', 'form_token', 'form_id',
325       'xmlsitemap',
326     );
327
328     // Allow the menu_attributes module to control the description field.
329     if ($menu_attributes) {
330       $ignore_children[] = 'description';
331     }
332
333     $ignore_types = array('actions', 'hidden', 'value', 'token');
334     if (in_array($child, $ignore_children) || !$type || in_array($type, $ignore_types)) {
335       continue;
336     }
337     $element[$child]['#access'] = $visible;
338   }
339   // Show/Hide the link options form elements based on menu item type of: link or view.
340   foreach (\Drupal\Core\Render\Element::children($element['options']) as $child) {
341     // Skip menu_view options.
342     $type = isset($element['options'][$child]['#type']) ? $element['options'][$child]['#type'] : '';
343     // Ensure necessary children are always present (regardless of their type).
344     $ignore_children = array('menu_views');
345     $ignore_types = array('hidden', 'value', 'token');
346     if (in_array($child, $ignore_children) || !$type || in_array($type, $ignore_types)) {
347       continue;
348     }
349     $element['options'][$child]['#access'] = $visible;
350   }
351   
352   // Place menu views in the options array.
353   $element['options']['menu_views'] = array(
354     '#type' => 'container',
355     '#tree' => TRUE,
356     '#weight' => 10,
357     '#access' => $access,
358   );
359   
360   // Create the actual Menu Views form.
361   _menu_views_form($item, $element['options']['menu_views'], $form, $form_state, $form_id);
362   
363   // Add menu views form handlers.
364   array_unshift($form['#validate'], '_menu_views_form_validate');
365   array_unshift($form['#submit'], '_menu_views_form_submit');
366 }
367
368
369 /**
370  * Adds Menu Views settings to an existing form.
371  *
372  * @param $item
373  *   The menu views item array passed by reference.
374  *   @see _menu_views_get_item()
375  * @param $element
376  *   The top level menu item edit form element passed by reference.
377  * @param $form
378  *   The complete form array passed by reference.
379  * @param $form_state
380  *   The complete form state array passed by reference.
381  */
382 function _menu_views_form(&$item, &$element, &$form, &$form_state, $form_id) {
383   $element['mlid'] = array(
384     '#type' => 'value',
385     '#value' => $item['mlid'],
386   );
387   $element['type'] = array(
388     '#type' => 'value',
389     '#value' => $item['type'],
390   );
391   $element['original_path'] = array(
392     '#type' => 'value',
393     '#value' => $item['original_path'],
394   );
395   
396   // Container for the actual view settings.
397   $element['view'] = array(
398     '#type' => 'container',
399     '#access' => $item['type'] == 'view' ? TRUE : FALSE,
400   );
401
402   $view_options = array();
403   $display_options = array();
404   foreach (views_get_enabled_views() as $view_name => $view) {
405     $view_options[$view_name] = $view->human_name . ' (' . $view_name . ')';
406     foreach ($view->display as $display_name => $display) {
407       if ('default' !== $display_name && 'page' !== $display_name && 'rss' !== $display_name) {
408         $display_options[$view_name][$display_name] = $display->display_title . ' (' . $display_name . ')';
409       }
410     }
411     // If view has no compatiable displays, remove the view as an option.
412     if (empty($display_options[$view_name])) {
413       unset($view_options[$view_name]);
414     }
415     else {
416       // Sort the displays for the view.
417       ksort($display_options[$view_name]);
418     }
419   }
420   ksort($view_options);
421   $element['view']['container'] = array(
422     '#type' => 'fieldset',
423     '#title' => t('View'),
424     '#parents' => _menu_views_form_parents($form),
425   );
426   $element['view']['container']['name'] = array(
427     '#type' => 'select',
428     '#title' => t('Name'),
429     '#empty_option' => t('- Select View -'),
430     '#description' => t('Select the name of a view to use. The following view displays cannot be used: Master (default), Page and RSS. If the view or display you are looking for does not exist, create a block display in that view.'),
431     '#required' => TRUE,
432     '#default_value' => $item['view']['name'],
433     '#options' => $view_options,
434     '#ajax' => array(
435       'callback' => '_menu_views_form_ajax',
436       'wrapper' => 'menu-edit-item-wrapper',
437     ),
438   );
439   if ($item['view']['name'] && !empty($display_options[$item['view']['name']])) {
440     $element['view']['container']['display'] = array(
441       '#type' => 'select',
442       '#title' => t('Display'),
443       '#description' => t('Select the name of a view display to use. The following view displays cannot be used: Master (default), Page and RSS. If the view or display you are looking for does not exist, create a block display in that view.'),
444       '#required' => TRUE,
445       '#empty_option' => t('- Select Display -'),
446       '#default_value' => $item['view']['display'],
447       '#options' => $display_options[$item['view']['name']],
448       '#ajax' => array(
449         'callback' => '_menu_views_form_ajax',
450         'wrapper' => 'menu-edit-item-wrapper',
451       ),
452     );
453     if ($item['view']['display']) {
454       $element['view']['container']['arguments'] = array(
455         '#type' => 'textfield',
456         '#title' => t('Arguments'),
457         '#description' => t('You can reference the node associated with this menu link by using <code>[menu-link:node:nid]</code>.<br />You can reference the node associated with the parent of this menu link by using <code>[menu-link:parent:node:nid]</code>.'),
458         '#default_value' => $item['view']['arguments'],
459       );
460       _menu_views_form_tokens_ui($element['view']['container']);
461       
462       // Advanced Settings.
463       $element['view']['settings'] = array(
464         '#type' => 'container',
465       );
466       $parents = _menu_views_form_parents($form);
467       $parents[] = 'settings';
468       
469       $parents_name = $parents;
470       $parents_name_first = array_shift($parents_name);
471       $parents_name = $parents_name_first . '[' . implode('][', $parents_name);
472       
473       $settings = &$element['view']['settings'];
474
475       // Wrapper Class
476       $settings['wrapper_classes'] = array(
477         '#type' => 'fieldset',
478         '#title' => t('Wrapper Classes'),
479         '#collapsible' => TRUE,
480         '#collapsed' => TRUE,
481         '#parents' => $parents,
482       );
483       $settings['wrapper_classes']['wrapper_classes'] = array(
484         '#type' => 'textfield',
485         '#description' => t('Provide any additional classes, separated by spaces.'),
486         '#default_value' => $item['view']['settings']['wrapper_classes'],
487       );
488
489       // View Title
490       $settings['title'] = array(
491         '#type' => 'fieldset',
492         '#title' => t('View Title'),
493         '#collapsible' => TRUE,
494         '#collapsed' => TRUE,
495         '#parents' => $parents,
496       );
497       $settings['title']['title'] = array(
498         '#type' => 'checkbox',
499         '#title' => t('Show view title'),
500         '#default_value' => $item['view']['settings']['title'],
501       );
502       $settings['title']['title_settings'] = array(
503         '#type' => 'container',
504         '#parents' => $parents,
505         '#states' => array(
506           'visible' => array(
507            ':input[name="' . $parents_name . '][title]"]' => array('checked' => TRUE),
508           ),
509         ),
510       );
511       $title = &$settings['title']['title_settings'];
512       // @FIXME
513 // // @FIXME
514 // // This looks like another module's variable. You'll need to rewrite this call
515 // // to ensure that it uses the correct configuration object.
516 // $title['title_wrapper'] = array(
517 //         '#type' => 'select',
518 //         '#title' => t('Element Wrapper'),
519 //         '#description' => t('Choose which element wrapper to use around the title of the view. Default: H3'),
520 //         '#default_value' => $item['view']['settings']['title_wrapper'],
521 //         '#options' => variable_get('views_field_rewrite_elements', array(
522 //           '' => t('- Use default -'),
523 //           '0' => t('- None -'),
524 //           'div' => 'DIV',
525 //           'span' => 'SPAN',
526 //           'h1' => 'H1',
527 //           'h2' => 'H2',
528 //           'h3' => 'H3',
529 //           'h4' => 'H4',
530 //           'h5' => 'H5',
531 //           'h6' => 'H6',
532 //           'p' => 'P',
533 //           'strong' => 'STRONG',
534 //           'em' => 'EM',
535 //         )),
536 //       );
537
538       $title['title_classes'] = array(
539         '#type' => 'textfield',
540         '#title' => t('Classes'),
541         '#description' => t('Provide any additional classes, separated by spaces. Title must use the element wrapper above for this take effect.'),
542         '#default_value' => $item['view']['settings']['title_classes'],
543       );
544       $title['title_override'] = array(
545         '#type' => 'textfield',
546         '#title' => t('Override Title'),
547         '#description' => t('Enter custom text to override title output. Default: Title will be provided from the view.'),
548         '#default_value' => $item['view']['settings']['title_override'],
549       );
550       _menu_views_form_tokens_ui($title);
551
552       // Breadcrumb
553       $settings['breadcrumb'] = array(
554         '#type' => 'fieldset',
555         '#title' => t('Breadcrumb'),
556         '#collapsible' => TRUE,
557         '#collapsed' => TRUE,
558         '#parents' => $parents,
559       );
560       $settings['breadcrumb']['breadcrumb'] = array(
561         '#type' => 'checkbox',
562         '#title' => t('Show breadcrumb link'),
563         '#default_value' => $item['view']['settings']['breadcrumb'],
564       );
565       $settings['breadcrumb']['breadcrumb_settings'] = array(
566         '#type' => 'container',
567         '#parents' => $parents,
568         '#states' => array(
569           'visible' => array(
570            ':input[name="' . $parents_name . '][breadcrumb]"]' => array('checked' => TRUE),
571           ),
572         ),
573       );
574       $breadcrumb = &$settings['breadcrumb']['breadcrumb_settings'];
575       $breadcrumb['breadcrumb_title'] = array(
576         '#type' => 'textfield',
577         '#title' => t('Link Title'),
578         '#description' => t('Title to use for the breadcrumb link. Note: If there is not a title provided by the view then the breadcrumb will not be displayed. Default: View Title'),
579         '#default_value' => $item['view']['settings']['breadcrumb_title'],
580       );
581       _menu_views_form_tokens_ui($breadcrumb);
582       $breadcrumb['breadcrumb_path'] = array(
583         '#type' => 'textfield',
584         '#title' => t('Link Path'),
585         '#description' => t('Path to use for the breadcrumb link. Default: %front.', array('%front' => '<front>')),
586         '#default_value' => $item['view']['settings']['breadcrumb_path'],
587       );      
588       _menu_views_form_tokens_ui($breadcrumb);
589     }
590   }
591 }
592
593
594 /**
595  * Ajax callback for re-rendering the attach views portion of the form.
596  */
597 function _menu_views_form_ajax(&$form, &$form_state, $form_id) {
598   if (isset($form['#node'])) {
599     return $form['menu']['link'];
600   }
601   return $form;
602 }
603
604
605 /**
606  * Validate handler for menu_edit_item form.
607  */
608 function _menu_views_form_validate($form, &$form_state) {
609   // Only run this validation when the form is fully submitted.
610   if ($form_state['submitted']) {
611     $item = _menu_views_get_item($form, $form_state);
612     if ($item['type'] == 'view') {
613       if (!$item['view']['name']) {
614         form_set_error(implode('][', _menu_views_form_parents($form)) . '][name', t('The menu item type for this @type is a view. A view name is required before this @type can be saved.', array('@type' => isset($form['#node']) ? 'node' : 'menu item')));
615       }
616       elseif (!$item['view']['display']) {
617         form_set_error(implode('][', _menu_views_form_parents($form)) . '][display', t('The menu item type for this @type is a view. A view display is required before this @type can be saved.', array('@type' => isset($form['#node']) ? 'node' : 'menu item')));
618       }
619     }
620   }
621 }
622
623
624 /**
625  * Submit handler for menu_edit_item form.
626  */
627 function _menu_views_form_submit($form, &$form_state) {
628   $values = &$form_state['values'];
629   if (isset($form['#node'])) {
630     $values = &$form_state['values']['menu'];
631   }
632   
633   // Get view settings from menu item.
634   $item = _menu_views_get_item($form, $form_state);
635   
636   // Remove this unecessary property from the values.
637   if (isset($values['menu_views'])) {
638     unset($values['menu_views']);
639   }
640   
641   // We really only want to intercept the menu edit item submit handle if this is actually a view.
642   if ($item['type'] == 'view') {
643     // If this is a new menu item, save a quick version of the menu item and return the mlid.
644     // The menu item will get updated with the rest of the values again shortly.
645     if (!$values['mlid']) {
646       $values['hidden'] = (int) !$values['enabled'];
647       $values['options']['attributes']['title'] = $values['description'];
648       list($values['menu_name'], $values['plid']) = explode(':', $values['parent']);
649       if (!$values['mlid'] = menu_link_save($values)) {
650         drupal_set_message(t('There was an error creating the menu item.'), 'error');
651       }
652     }
653     $default = _menu_views_default_values();
654     $item = array(
655       // The mlid should remain constant, always use the information provided by the menu module and not this one.
656       'mlid' => $values['mlid'],
657       'type' => $item['type'],
658       'original_path' => $item['original_path'],
659       'view' => $item['view'],
660     );
661     // Replace the menu views values in the menu item's options.
662     $values['options']['menu_views'] = _menu_views_array_merge_recursive($default, $item);
663   }
664 }
665
666
667 /**
668  * Return a list of menu items that are valid possible parents for the given menu item.
669  *
670  * @param $menus
671  *   An array of menu names and titles, such as from menu_get_menus().
672  * @param $item
673  *   The menu item or the node type for which to generate a list of parents.
674  *   If $item['mlid'] == 0 then the complete tree is returned.
675  * @param $type
676  *   The node type for which to generate a list of parents.
677  *   If $item itself is a node type then $type is ignored.
678  * @return
679  *   An array of menu link titles keyed on the a string containing the menu name
680  *   and mlid. The list excludes the given item and its children.
681  *
682  * @todo This has to be turned into a #process form element callback. The
683  *   'menu_override_parent_selector' variable is entirely superfluous.
684  */
685 function _menu_views_parent_options($menus, $item, $type = '') {
686   // The menu_links table can be practically any size and we need a way to
687   // allow contrib modules to provide more scalable pattern choosers.
688   // hook_form_alter is too late in itself because all the possible parents are
689   // retrieved here, unless menu_override_parent_selector is set to TRUE.
690   // @FIXME
691 // // @FIXME
692 // // This looks like another module's variable. You'll need to rewrite this call
693 // // to ensure that it uses the correct configuration object.
694 // if (variable_get('menu_override_parent_selector', FALSE)) {
695 //     return array();
696 //   }
697
698
699   $available_menus = array();
700   if (!is_array($item)) {
701     // If $item is not an array then it is a node type.
702     // Use it as $type and prepare a dummy menu item for _menu_get_options().
703     $type = $item;
704     $item = array('mlid' => 0);
705   }
706   if (isset($item['mlid']) && $item['mlid']) {
707     $item = menu_link_load($item['mlid']);
708   }
709   if (empty($type)) {
710     // If no node type is set, use all menus given to this function.
711     $available_menus = $menus;
712   }
713   else {
714     // If a node type is set, use all available menus for this type.
715     // @FIXME
716 // // @FIXME
717 // // The correct configuration object could not be determined. You'll need to
718 // // rewrite this call manually.
719 // $type_menus = variable_get('menu_options_' . $type, array('main-menu' => 'main-menu'));
720
721     foreach ($type_menus as $menu) {
722       $available_menus[$menu] = $menu;
723     }
724   }
725
726   return _menu_views_get_options($menus, $available_menus, $item);
727 }
728
729 /**
730  * Helper function to get the items of the given menu.
731  */
732 function _menu_views_get_options($menus, $available_menus, $item) {
733   // If the item has children, there is an added limit to the depth of valid parents.
734   if (isset($item['parent_depth_limit'])) {
735     $limit = $item['parent_depth_limit'];
736   }
737   else {
738     $limit = _menu_parent_depth_limit($item);
739   }
740
741   $options = array();
742   foreach ($menus as $menu_name => $title) {
743     if (isset($available_menus[$menu_name])) {
744       // @FIXME
745 // menu_tree_all_data() is gone in Drupal 8. To generate or work with menu trees, you'll need to
746 // use the menu.link_tree service.
747 // 
748 // 
749 // @see https://www.drupal.org/node/2226481
750 // @see https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Menu%21MenuLinkTree.php/class/MenuLinkTree/8
751 // $tree = menu_tree_all_data($menu_name, NULL);
752
753       $menu_tree = \Drupal::service('toolbar.menu_tree');
754
755       $tree = MenuLinkTreeInterface::load();
756
757       $options[$menu_name . ':0'] = '<' . $title . '>';
758       _menu_views_parents_recurse($tree, $menu_name, '--', $options, $item['mlid'], $limit);
759     }
760   }
761   return $options;
762 }
763
764 /**
765  * Recursive helper function for menu_parent_options().
766  */
767 function _menu_views_parents_recurse($tree, $menu_name, $indent, &$options, $exclude, $depth_limit) {
768   foreach ($tree as $data) {
769     if ($data['link']['depth'] > $depth_limit) {
770       // Don't iterate through any links on this level.
771       break;
772     }
773     if ($data['link']['mlid'] != $exclude && $data['link']['hidden'] >= 0) {
774       $item = _menu_views_get_item($data['link']);
775       _menu_views_tokenize($item);
776       if ($item['type'] == 'view' && $item['view']['name'] && $item['view']['display']) {
777         $title = t($item['view']['name']) . '-' . t($item['view']['display']);
778         $view_title = \Drupal\Component\Utility\Xss::filterAdmin($item['view']['settings']['title_override']);
779         if (empty($view_title) && ($view = views_get_view($item['view']['name']))) {
780           if ($view->access($item['view']['display']) && $view->set_display($item['view']['display'])) {
781             $view->set_arguments(explode('/', $item['view']['arguments']));
782             $view_title = \Drupal\Component\Utility\Xss::filterAdmin($view->get_title());
783           }
784           $view->destroy();
785         }
786         if (!empty($view_title)) {
787           $title = $view_title . ' (' . $title . ')';
788         }
789         $title = $indent . ' [view] ' . \Drupal\Component\Utility\Unicode::truncate($title, 30, TRUE, FALSE);
790       }
791       else {
792         $title = $indent . ' ' . \Drupal\Component\Utility\Unicode::truncate($data['link']['title'], 30, TRUE, FALSE);
793       }
794       if ($data['link']['hidden']) {
795         $title .= ' (' . t('disabled') . ')';
796       }
797       $options[$menu_name . ':' . $data['link']['mlid']] = $title;
798       if ($data['below']) {
799         _menu_views_parents_recurse($data['below'], $menu_name, $indent . '--', $options, $exclude, $depth_limit);
800       }
801     }
802   }
803 }