-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathreferences_dialog.module
849 lines (788 loc) · 29 KB
/
references_dialog.module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
<?php
/**
* @file
* This the main module file.
*/
/**
* Implements hook_autoload_info().
*/
function references_dialog_autoload_info() {
return array(
'references_dialog_plugin_display' => 'views/references_dialog_plugin_display.inc',
);
}
/**
* Implements hook_menu().
*/
function references_dialog_menu() {
$items = array();
// This redirect callback is used when adding and editing content in
// the overlay. When content is created or edited, we are directed here,
// so we can act properly on entities.
$items['references-dialog/redirect/%/%'] = array(
'page callback' => 'references_dialog_redirect_page',
'page arguments' => array(2, 3),
'access callback' => 'references_dialog_redirect_access',
'access arguments' => array(2, 3),
);
return $items;
}
/**
* Implements hook_theme().
*/
function references_dialog_theme() {
return array(
'references_dialog_links' => array(
'variables' => array('links' => NULL),
),
);
}
/**
* Implements hook_element_info().
*/
function references_dialog_element_info() {
$types['references_dialog'] = array(
'#input' => FALSE ,
'#after_build' => array('references_dialog_build_element'),
'#attached' => references_dialog_attached(),
);
return $types;
}
/**
* Get everything that needs to be attached in order for the links to work.
*/
function references_dialog_attached() {
return array(
'js' => array(backdrop_get_path('module', 'references_dialog') . '/js/references-dialog.js'),
'css' => array(backdrop_get_path('module', 'references_dialog') . '/css/references-dialog-admin.css'),
'library' => array(array('system', 'ui.dialog')),
);
}
/**
* Implements hook_element_info_alter().
* Add #after_builds to widgets that needs them.
*/
function references_dialog_element_info_alter(&$info) {
foreach (references_dialog_widgets() as $widget) {
// If this element type is specified as a type that a widget should be
// attached to, go ahead and make it so.
if (isset($info[$widget['element_type']]) && (!isset($info[$widget['element_type']]['#after_build']) || !in_array('references_dialog_process_widget', $info[$widget['element_type']]['#after_build']))) {
$info[$widget['element_type']]['#after_build'][] = 'references_dialog_process_widget';
}
}
}
/**
* Implements hook_admin_paths().
*/
function references_dialog_admin_paths() {
// We only activate admin theme if we use the admin theme
// when editing nodes.
if (config_get('system.core', 'node_admin_theme')) {
return array('references-dialog/search/*' => TRUE);
}
}
/**
* Get search views attached to a particular field instance.
* @param array instance a field instance.
*/
function references_dialog_field_get_search_views(array $instance) {
return references_dialog_get_search_views(implode(':', array($instance['entity_type'], $instance['field_name'], $instance['bundle'])));
}
/**
* Get all search views that are available for a particular attachable.
* @param $attachable
* the name of the attachable to look for.
*/
function references_dialog_get_search_views($attachable) {
$search_views = &backdrop_static(__FUNCTION__, array());
if (!isset($search_views[$attachable])) {
$search_views[$attachable] = array();
// Get all views that has a references_dialog display.
$results = references_dialog_get_applicable_views();
foreach ($results as $view_name => $result) {
foreach ($result as $display_name => $result_displays) {
foreach ($result_displays['attachables'] as $name => $view_attachable) {
if ($attachable == $view_attachable) {
$search_views[$attachable][$view_name] = $result_displays;
}
}
}
}
}
return $search_views[$attachable];
}
function references_dialog_get_applicable_views() {
$views = &backdrop_static(__FUNCTION__, FALSE);
if (!$views) {
$views = cache_get('references_dialog_views');
$views = !empty($views) ? $views->data : FALSE;
}
if (!empty($views)) {
return $views;
}
$views = array();
// Get all views that has a references_dialog display.
$results = views_get_applicable_views('references_dialog display');
foreach ($results as $result) {
list($view, $display) = $result;
if (is_object($view)) {
$views[$view->name][$display] = array(
'display' => $display,
'title' => isset($view->display[$view->current_display]->display_options['title']) ?
$view->display[$view->current_display]->display_options['title'] : t('Search'),
'attachables' => $view->display_handler->get_option('attach'),
);
}
}
cache_set('references_dialog_views', $views);
return $views;
}
/**
* Implements hook_widget_info_alter().
* Adds settings that we need to declare to widgets we are extending.
*/
function references_dialog_field_widget_info_alter(array &$info) {
foreach (references_dialog_widgets() as $widget_name => $widget_info) {
if (isset($info[$widget_name]['settings'])) {
foreach (array_keys($widget_info['operations']) as $operation) {
$info[$widget_name]['settings']['references_dialog_' . $operation] = 0;
// Add search view setting if we have search.
if ($operation == 'search') {
$info[$widget_name]['settings']['references_dialog_search_view'] = '';
}
}
}
}
}
/**
* Get instances appropriate for a search view on a particular entity type.
* @param string $entity_type name of the entity type.
* @return array of appropriate instances.
*/
function references_dialog_get_search_view_attachables($entity_type = NULL) {
$attachables = module_invoke_all('references_dialog_search_attachables');
if (isset($entity_type)) {
return $attachables[$entity_type];
}
else {
return $attachables;
}
}
/**
* Get an attachable by name
* @param $entity_type
* the type of entity the attacable is attached to.
* @param $name
* The name of the attachable.
*/
function references_dialog_get_attachable($entity_type, $name) {
$attachables = module_invoke_all('references_dialog_search_attachables');
return $attachables[$entity_type][$name];
}
/**
* Implements hook_references_dialog_search_attachables().
*/
function references_dialog_references_dialog_search_attachables() {
$fields = field_info_fields();
$widgets = field_info_widget_types();
$dialog_widgets = references_dialog_widgets();
$applicable_instances = array();
foreach ($fields as $field_name => $field) {
foreach ($field['bundles'] as $entity_type => $bundles) {
foreach ($bundles as $bundle_name) {
$instance = field_info_instance($entity_type, $field_name, $bundle_name);
$widget_type = $instance['widget']['type'];
if (in_array($widget_type, array_keys($dialog_widgets)) && $instance['widget']['settings']['references_dialog_search']) {
// If the entity type is specified, in the declaration, add it here.
$dialog_widget = $dialog_widgets[$widget_type];
if (isset($dialog_widget['entity_type'])) {
$attachable_type = $dialog_widget['entity_type'];
}
elseif (isset($dialog_widgets[$instance['widget']['type']]['type_callback'])) {
$attachable_type = $dialog_widget['type_callback']($instance, $field);
}
if (isset($attachable_type)) {
$applicable_instances[$attachable_type][$entity_type . ':' . $field_name . ':' . $bundle_name] = array(
'label' => $instance['bundle'] . ': ' . $instance['label'],
'query' => 'references_dialog_field_attachable_query',
'widget' => $dialog_widget,
);
}
}
}
}
}
return $applicable_instances;
}
/**
* This query is used by field references dialog attachables.
* @param View $view
* The view to work with.
*/
function references_dialog_field_attachable_query($view) {
list($entity_type, $field_name, $bundle_name) = explode(':', $view->references_dialog['attachable']['name']);
$instance = field_info_instance($entity_type, $field_name, $bundle_name);
$field_info = field_info_field($field_name);
$dialog_widget = references_dialog_widget_load($instance['widget']['type']);
if (isset($dialog_widget['views_query']) && function_exists($dialog_widget['views_query'])) {
$dialog_widget['views_query']($view, $instance, $field_info);
}
}
/**
* Return an array of supported widgets.
*/
function references_dialog_widgets() {
$widgets = &backdrop_static(__FUNCTION__);
if ($widgets === NULL) {
$widgets = module_invoke_all('references_dialog_widgets');
backdrop_alter('references_dialog_widgets', $widgets);
}
return $widgets;
}
/**
* Load a particular widget.
* @param string $widget the name of the widget.
* @return array the widget definition.
*/
function references_dialog_widget_load($widget) {
$widgets = references_dialog_widgets();
return $widgets[$widget];
}
/**
* Implements hook_form_alter().
*/
function references_dialog_form_field_ui_field_edit_form_alter(&$form, $form_state) {
if (array_key_exists($form['instance']['widget']['type']['#value'], references_dialog_widgets())) {
$field = $form['#field'];
$instance = field_info_instance($form['instance']['entity_type']['#value'], $form['instance']['field_name']['#value'], $form['instance']['bundle']['#value']);
if (isset($form['instance']['widget']['settings'])) {
$form['instance']['widget']['settings'] += references_dialog_settings_form($field, $instance);
}
else {
$form['instance']['widget']['settings'] = references_dialog_settings_form($field, $instance);
}
}
}
/**
* A widget settings form for our references dialog fields.
*/
function references_dialog_settings_form($field, $instance) {
$widget = $instance['widget'];
$defaults = field_info_widget_settings($widget['type']);
$settings = array_merge($defaults, $widget['settings']);
$dialog_widget = references_dialog_widget_load($widget['type']);
// Add our own additions.
foreach ($dialog_widget['operations'] as $operation => $dialog_settings) {
$form['references_dialog_' . $operation] = array(
'#type' => 'checkbox',
'#title' => check_plain($dialog_settings['title']),
'#default_value' => isset($settings['references_dialog_' . $operation]) ? $settings['references_dialog_' . $operation] : FALSE,
);
}
return $form;
}
/**
* Menu access checker for references_dialog
*/
function references_dialog_search_access($entity_type, $field_name, $bundle_name) {
return TRUE;
}
/**
* Add our references dialog fields to the existing element
*/
function references_dialog_process_widget(&$element) {
if (!isset($element['#entity_type'])) {
return $element;
}
$item = $element['#value'];
$field = field_info_field($element['#field_name']);
$instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']);
$widget_settings = $instance['widget']['settings'];
$widget_type = $instance['widget']['type'];
$widgets = references_dialog_widgets();
// Bail if we don't have anything to do here.
if (!in_array($widget_type, array_keys($widgets))) {
return $element;
}
$dialog_widget = references_dialog_widget_load($widget_type);
// Attach javascript and CSS needed.
$attached = references_dialog_attached();
$element['#attached']['js'][] = $attached['js'][0];
$element['#attached']['js'][] = references_dialog_js_settings($element['#id'], array('format' => $dialog_widget['format']));
$element['#attached']['css'][] = $attached['css'][0];
$element['#attached']['library'][] = $attached['library'][0];
$link_options = array('attributes' => array('class' => array('references-dialog-activate')));
$dialog_links = array();
foreach ($dialog_widget['operations'] as $operation => $settings) {
if (isset($widget_settings['references_dialog_' . $operation]) && $widget_settings['references_dialog_' . $operation]) {
$links = $settings['function']($element, $widget_settings, $field, $instance);
foreach ($links as $link) {
$link['attributes']['class'][] = $operation . '-dialog';
// Allow other modules to alter the link
backdrop_alter('references_dialog_link', $link, $element);
$dialog_links[] = references_dialog_link($link);
}
}
}
if (count($dialog_links)) {
// We add a div directly into the markup here since we really need it in order
// to make sure the javascript works.
$element['#suffix'] = '<div class="dialog-links ' . $element['#id'] . '">' . theme('references_dialog_links', array('links' => $dialog_links)) . '</div>';
}
return $element;
}
function references_dialog_build_element($element) {
$dialog_links = array();
$element['#attached']['js'][] = references_dialog_js_settings($element['#id'], array('format' => $element['#format'], 'target' => $element['#target']));
if (isset($element['#operations'])) {
foreach ($element['#operations'] as $operation => $link) {
$link['attributes']['class'][] = $operation . '-dialog';
$dialog_links[] = references_dialog_link($link);
}
}
if (isset($element['#attachable'])) {
$dialog_links = array_merge($dialog_links, references_dialog_get_views_search_links($element['#attachable']));
}
if (count($dialog_links)) {
// We add a div directly into the markup here since we really need it in order
// to make sure the javascript works.
$element['#suffix'] = '<div class="dialog-links ' . $element['#id'] . '">' . theme('references_dialog_links', array('links' => $dialog_links)) . '</div>';
}
return $element;
}
/**
* Attach necessary info to a link definition.
*/
function references_dialog_link($link) {
if (!isset($link['attributes']['class']) || !in_array('references-dialog-activate', $link['attributes']['class'])) {
$link['attributes']['class'][] = 'references-dialog-activate';
}
return $link;
}
function references_dialog_js_settings($id, array $settings) {
if (isset($settings['callback_path'])) {
$settings['callback_path'] = url($settings['callback_path']);
}
return array(
'data' => array(
'ReferencesDialog' => array(
'fields' => array(
$id => $settings,
),
),
),
'type' => 'setting',
);
}
/**
* Implements hook_entity_insert().
*/
function references_dialog_entity_insert($entity, $entity_type) {
// If we are in a dialog, we want to make sure that we redirect to the
// the close dialog page, so that the dialog may be closed.
if (references_dialog_in_dialog() && references_dialog_close_on_submit()) {
references_dialog_close_on_redirect($entity, $entity_type);
}
}
/**
* Implements hook_entity_update().
*/
function references_dialog_entity_update($entity, $entity_type) {
if (references_dialog_in_dialog() && references_dialog_close_on_submit()) {
references_dialog_close_on_redirect($entity, $entity_type);
}
}
/**
* Sets our destination parameter so that the dialog will close itself after
* redirect is completed.
*/
function references_dialog_close_on_redirect($entity, $entity_type) {
$entity_info = entity_get_info($entity_type);
// We use $_GET['destination'] since that overrides anything that happens
// in the form. It is a hack, but it is very effective, since we don't have
// to be worried about getting overrun by other form submit handlers.
$_GET['destination'] = 'references-dialog/redirect/' .
$entity->{$entity_info['entity keys']['id']} . '/' .
$entity_type .
'?references-dialog-close=1&render=references-dialog';
}
/**
* Implements hook_init().
*/
function references_dialog_init() {
if (references_dialog_in_dialog()) {
admin_bar_suppress(TRUE);
// Hack to provide "Content only" layout, since page.tpl.php template is not an option for backdrop
// see https://github.com/backdrop/backdrop-issues/issues/1483#issuecomment-169173412
//- $_SERVER['HTTP_ACCEPT'] = 'text/x-lightbox';
// Does not work any more with backdrop 1.3.4
// see https://github.com/backdrop/backdrop/pull/1290
// Let's issue another fake header...
$_SERVER['HTTP_X_REQUESTED_WITH'] = 'FakeHttpRequest';
// another workaround could be :
// $config = config('system.core');
// $config->set('menu_route_handler', 'menu_default_route_handler');
// ultimately, if this gets in core...
layout_suppress(TRUE);
backdrop_add_css(backdrop_get_path('module', 'references_dialog') . '/css/references-dialog-search.css');
}
}
/**
* Implements hook_form_BASE_FORM_ID_alter().
*
* Adds minimal layout for theming the node form in a dialog.
*/
function references_dialog_form_node_form_alter(&$form, $form_state) {
if (arg(0) == 'node' && references_dialog_in_dialog()) {
$form['#prefix'] = '
<div id="references-dialog-page"><div class="l-container">
<main class="l-content" role="main">
';
$form['#suffix'] = '
</main></div></div>
';
$form['actions']['cancel']['#access'] = FALSE;
}
}
/**
* Menu callback for fetching a search view.
* @param $view_name a view to use.
* @param $display_name the display name.
* @param $instance_info information aboutythe current display in a packed form.
*/
function references_dialog_search_view($view_name, $display_name, $attachable) {
$args = func_get_args();
$args = array_slice($args, 3);
$view = views_get_view($view_name);
// Find the entity that matches our base table.
$entities = entity_get_info();
foreach ($entities as $entity_type => $entity_info) {
if ($entity_info['base table'] == $view->base_table) {
break;
}
}
// Add some nice data about our field that the display handler can use.
$view->references_dialog = array(
'attachable' => references_dialog_get_attachable($entity_type, $attachable) + array('name' => $attachable),
);
return $view->execute_display($display_name, $args);
}
/**
* Implements hook_hook_info().
*/
function references_dialog_hook_info() {
$hooks = array();
$hooks['references_dialog_widgets'] = array(
'group' => 'dialog_widgets',
);
return $hooks;
}
function references_dialog_get_field_search_links($element, $widget_settings, $field, $instance) {
// We pack the necessary information for getting a field instance together in the
// url, so that we can retrieve the field instance and attach it to the view
// later on.
$attachable = implode(':', array($instance['entity_type'], $instance['field_name'], $instance['bundle']));
return references_dialog_get_views_search_links($attachable);
}
/**
* Get all views search links for an instance.
* This function should be used by references dialog widgets that uses
* views for it's search functionality.
* @param $instance
*/
function references_dialog_get_views_search_links($attachable) {
$applicable_views = references_dialog_get_search_views($attachable);
$links = array();
foreach ($applicable_views as $view_name => $view) {
$links[] = references_dialog_link(array(
'title' => $view['title'],
'href' => 'references-dialog/search/' . $view_name . '/' . $view['display'] . '/' . $attachable,
));
}
return $links;
}
/**
* Implements hook_preprocess_page().
*/
function references_dialog_preprocess_page(&$variables) {
if (references_dialog_in_dialog()) {
$variables['page'] = '<div id="references-dialog-page">' . $variables['page'] . '</div>';
backdrop_add_js('file', '/js/search-reference.js');
}
}
/**
* Check if we are in a references dialog.
* @return boolean if we are in a dialog.
*/
function references_dialog_in_dialog() {
return (isset($_GET['render']) && $_GET['render'] == 'references-dialog') ||
// We are always in a dialog if we are on a references dialog search page,
// otherwise we will have a hard time with views exposed filters.
strstr(current_path(), 'references-dialog/search') !== FALSE;
}
/**
* Check if we should close the dialog upon submition.
*/
function references_dialog_close_on_submit() {
return (!isset($_GET['closeonsubmit']) || $_GET['closeonsubmit']);
}
/**
* Implements of hook_views_api().
*/
function references_dialog_views_api() {
return array(
'api' => 3,
'path' => backdrop_get_path('module', 'references_dialog') . '/views',
);
}
/**
* Implements of hook_views_plugins().
*/
function references_dialog_views_plugins() {
return array(
'display' => array(
'references_dialog' => array(
'title' => t('Reference dialog Search'),
'admin' => t('References'),
'theme' => 'views_view',
'help' => t('A view that can be used when referencing content.'),
'handler' => 'references_dialog_plugin_display',
'use ajax' => TRUE,
'use pager' => TRUE,
'uses hook menu' => TRUE,
'help topic' => 'references-dialog',
'references_dialog display' => TRUE,
'path' => backdrop_get_path('module', 'references_dialog') . '/views',
),
),
);
}
function references_dialog_redirect_access() {
// @todo It is not really a security issue, but we should probably check
// that you can create the content you just created (silly), to access
// this page.
return TRUE;
}
/**
* Page callback for our redirect page.
*/
function references_dialog_redirect_page($entity_id, $entity_type) {
// Get some information about the entity we are dealing with.
$entity = entity_load($entity_type, array($entity_id));
$entity = reset($entity);
$entity_info = entity_get_info($entity_type);
$entity_id = $entity->{$entity_info['entity keys']['id']};
$entity_title = entity_label($entity_type, $entity);
// Add appropriate javascript that will be used by the parent page to
// fill in the required data.
if (isset($entity_id) && references_dialog_in_dialog() && isset($_GET['references-dialog-close'])) {
backdrop_add_js(backdrop_get_path('module', 'references_dialog') . '/js/references-dialog-child.js');
backdrop_add_js(array(
'ReferencesDialog' => array(
'entity_id' => $entity_id,
'title' => $entity_title,
'entity_type' => $entity_type,
),
), 'setting');
}
return '';
}
/**
* Implements hook_references_dialog_entity_admin_paths().
*/
function references_dialog_references_dialog_entity_admin_paths() {
// We define the add and edit page callbacks for core entities here.
$admin_paths = array(
'node' => array(
'add' => 'node/add/[bundle-sanitized]',
'edit' => 'node/[entity_id]/edit',
),
'taxonomy_term' => array(
'edit' => 'taxonomy/term/[entity_id]/edit',
'add' => 'admin/structure/taxonomy/[bundle]/add',
),
// Dealing with taxonomy vocabularies like this is kind of silly,
// and accessing them is a bit harder since their admin page is accessible
// through their machine name, so we leave it at just adding them for now.
'taxonomy_vocabulary' => array(
'add' => 'admin/structure/taxonomy/add',
),
'comment' => array(
'edit' => 'comment/[entity_id]/edit',
),
'user' => array(
'add' => 'admin/people/create',
'edit' => 'user/[entity_id]/edit',
),
);
// The media module adds an edit callback for media as well.
// Note: this will probably not work until file_entity provides an access
// API, see http://backdrop.org/node/1227706
if (module_exists('media')) {
$admin_paths['file'] = array(
'edit' => 'media/[entity_id]/edit',
);
}
// Bean provides add and edit paths for custom entities.
if (module_exists('bean')) {
$admin_paths['bean'] = array(
'add' => 'block/add/[bundle-sanitized]',
'edit' => 'block/[entity_id]/edit',
);
}
return $admin_paths;
}
/**
* Get the admin path (edit/add) page for a particular entity
* @param string $entity_type the entity type
* @param string $op Which operation to perform. Either "edit" or "add".
* @param string $bundle The bundle to use.
* @param mixed $entity The entity to edit. This is only used with the "edit" operation.
* @return string The path where the entity can be edited or created.
*/
function references_dialog_get_admin_path($entity_type, $op, $bundle = NULL, $entity = NULL) {
// Let's cache the paths.
$paths = &backdrop_static(__FUNCTION__ , NULL);
if (!isset($paths)) {
$paths = module_invoke_all('references_dialog_entity_admin_paths');
}
if (isset($paths[$entity_type]) && isset($paths[$entity_type][$op])) {
$path = $paths[$entity_type][$op];
// Create a wrapper, so we can deal with this in a sane way.
$wrapper = entity_metadata_wrapper($entity_type, $entity);
// Replace [entity_id] with the entity id.
if (isset($entity)) {
$path = str_replace('[entity_id]', $wrapper->getIdentifier(), $path);
}
if (!$bundle) {
$bundle = $wrapper->getBundle();
}
if ($bundle) {
$path = str_replace('[bundle]', $bundle, $path);
// Some entities (like node) provide a sort of sanitized version.
// This makes sure we support this.
$bundle = strtr($bundle, array('_' => '-'));
$path = str_replace('[bundle-sanitized]', $bundle, $path);
}
return $path;
}
return FALSE;
}
/**
* Theme function for theming the links for opening
* the references dialog.
*/
function theme_references_dialog_links($variables) {
return theme('links', array('links' => $variables['links'], 'attributes' => array('class' => array('references-dialog-links'))));
}
/**
* Implements hook_field_widget_info().
*/
function references_dialog_field_widget_info() {
return array(
'references_dialog_term_reference' => array(
'label' => t('Autocomplete term widget for References Dialog'),
'field types' => array('taxonomy_term_reference'),
'settings' => array(
'size' => 60,
'autocomplete_path' => 'taxonomy/autocomplete',
'autocomplete_match' => 'starts_with',
),
),
);
}
/**
* Implements hook_field_widget_settings_form().
*/
function references_dialog_field_widget_settings_form($field, $instance) {
$widget = $instance['widget'];
$defaults = field_info_widget_settings($widget['type']);
$settings = array_merge($defaults, $widget['settings']);
$form = array();
if ($widget['type'] == 'references_dialog_term_reference') {
$form['autocomplete_match'] = array(
'#type' => 'select',
'#title' => t('Autocomplete matching'),
'#default_value' => $settings['autocomplete_match'],
'#options' => array(
'starts_with' => t('Starts with'),
'contains' => t('Contains'),
),
'#description' => t('Select the method used to collect autocomplete suggestions. Note that <em>Contains</em> can cause performance issues on sites with thousands of nodes.'),
);
$form['size'] = array(
'#type' => 'number',
'#title' => t('Size of textfield'),
'#default_value' => $settings['size'],
'#min' => 0,
'#required' => TRUE,
);
}
return $form;
}
/**
* Implements hook_field_widget_form().
*/
function references_dialog_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
switch ($instance['widget']['type']) {
case 'references_dialog_term_reference':
if (isset($items[$delta]['tid'])) {
$term = taxonomy_term_load($items[$delta]['tid']);
$value = $term->name;
}
else {
$value = NULL;
}
$element += array(
'#type' => 'textfield',
'#default_value' => $value,
'#autocomplete_path' => $instance['widget']['settings']['autocomplete_path'] . '/' . $field['field_name'],
'#size' => $instance['widget']['settings']['size'],
'#maxlength' => NULL,
'#element_validate' => array('references_dialog_term_reference_autocomplete_validate'),
);
break;
}
return array('tid' => $element);
}
/**
* Form element validate handler for taxonomy term autocomplete element.
*/
function references_dialog_term_reference_autocomplete_validate($element, &$form_state) {
// Autocomplete widgets do not send their tids in the form, so we must detect
// them here and process them independently.
$value = array();
if ($element['#value']) {
$term = FALSE;
$field = field_widget_field($element, $form_state);
$instance = field_widget_instance($element, $form_state);
// Check whether we have an explicit "[tid:n]" input.
preg_match('/^(?:\s*|(.*) )?\[\s*tid\s*:\s*(\d+)\s*\]$/', $element['#value'], $matches);
if (!empty($matches)) {
// Explicit tid.
list(, $term_name, $tid) = $matches;
if (!empty($term_name)) {
$term = taxonomy_term_load($tid);
}
}
else {
// Collect candidate vocabularies.
$vocabularies = array();
foreach ($field['settings']['allowed_values'] as $tree) {
if ($vocabulary = taxonomy_vocabulary_load($tree['vocabulary'])) {
$vocabularies[$vocabulary->machine_name] = $vocabulary->machine_name;
}
}
if ($possibilities = taxonomy_term_load_multiple(array(), array('name' => trim($element['#value']), 'vocabulary' => array_keys($vocabularies)))) {
$term = array_pop($possibilities);
}
}
if ($term) {
$value = $term->tid;
}
else {
form_error($element, t('%name: found no valid post for this value.', array('%name' => $instance['label'])));
}
}
form_set_value($element, $value, $form_state);
}