1
|
<?php
|
2
|
|
3
|
/**
|
4
|
* @file
|
5
|
* Helper functions for menu administration.
|
6
|
*/
|
7
|
|
8
|
|
9
|
/**
|
10
|
* Produces a menu translation form.
|
11
|
*/
|
12
|
function i18n_menu_translation_form($form, $form_state, $translation_set = NULL, $item = NULL) {
|
13
|
$translation_set = $translation_set ? $translation_set : i18n_translation_set_build('menu_link');
|
14
|
$form['translation_set'] = array('#type' => 'value', '#value' => $translation_set);
|
15
|
$translations = $translation_set->get_translations();
|
16
|
// What to do with title? Let's make it a hidden field for now, some tests relay on it
|
17
|
$form['title'] = array('#type' => 'hidden', '#default_value' => $translation_set->title);
|
18
|
if ($item && ($lang = i18n_object_langcode($item))) {
|
19
|
$translations[$lang] = $item;
|
20
|
}
|
21
|
$item = $item ? $item : array('mlid' => 0, 'menu_name' => '', 'plid' => 0);
|
22
|
$item_lang = i18n_object_langcode($item);
|
23
|
$form['translations'] = array(
|
24
|
'#type' => 'fieldset',
|
25
|
'#title' => t('Translations'),
|
26
|
'#tree' => TRUE,
|
27
|
'#description' => t('Enter items that will be considered as translations of each other.'),
|
28
|
);
|
29
|
foreach (i18n_language_list() as $langcode => $language_name) {
|
30
|
if ($langcode == $item_lang) {
|
31
|
// We've got a predefined item for this language
|
32
|
$form['translations'][$langcode] = array('#type' => 'value', '#value' => $item['menu_name'] . ':' . $item['mlid']);
|
33
|
$form['translations']['display'] = array(
|
34
|
'#type' => 'item',
|
35
|
'#title' => $language_name,
|
36
|
'#markup' => check_plain($item['link_title']),
|
37
|
);
|
38
|
}
|
39
|
else {
|
40
|
// Generate a list of possible parents (not including this link or descendants).
|
41
|
$options = i18n_menu_parent_options(menu_get_menus(), $item, $langcode);
|
42
|
$default = isset($translations[$langcode]) ? $translations[$langcode]['menu_name'] . ':' . $translations[$langcode]['mlid'] : 'navigation:0';
|
43
|
if (!isset($options[$default])) {
|
44
|
$default = 'navigation:0';
|
45
|
}
|
46
|
$form['translations'][$langcode] = array(
|
47
|
'#type' => 'select',
|
48
|
'#title' => $language_name,
|
49
|
'#default_value' => $default,
|
50
|
'#options' => $options,
|
51
|
'#description' => t('The maximum depth for a link and all its children is fixed at !maxdepth. Some menu links may not be available as parents if selecting them would exceed this limit.', array('!maxdepth' => MENU_MAX_DEPTH)),
|
52
|
'#attributes' => array('class' => array('menu-title-select')),
|
53
|
);
|
54
|
}
|
55
|
}
|
56
|
$form['actions'] = array('#type' => 'actions');
|
57
|
$form['actions']['update'] = array('#type' => 'submit', '#value' => t('Save'));
|
58
|
if (!empty($translation_set->tsid)) {
|
59
|
$form['actions']['delete'] = array('#type' => 'submit', '#value' => t('Delete'));
|
60
|
}
|
61
|
return $form;
|
62
|
}
|
63
|
|
64
|
/**
|
65
|
* Process form validation
|
66
|
*/
|
67
|
function i18n_menu_translation_form_validate($form, &$form_state) {
|
68
|
if ($form_state['values']['op'] == t('Save')) {
|
69
|
$selected = 0;
|
70
|
// example array('en' => 'navigation:0')
|
71
|
$mlids = array_filter($form_state['values']['translations']);
|
72
|
foreach ($mlids as $lang => $item_name) {
|
73
|
list($menu_name, $mlid) = explode(':', $item_name);
|
74
|
if ($mlid && ($item = menu_link_load($mlid)) && i18n_object_langcode($item)) {
|
75
|
$selected++;
|
76
|
}
|
77
|
else {
|
78
|
unset($form_state['values']['translations'][$lang]);
|
79
|
}
|
80
|
}
|
81
|
if ($selected < 1) {
|
82
|
form_set_error('translations', t('There are no translations to save.'));
|
83
|
}
|
84
|
}
|
85
|
}
|
86
|
|
87
|
/**
|
88
|
* Menu item translation form submission
|
89
|
*/
|
90
|
function i18n_menu_translation_form_submit($form, &$form_state) {
|
91
|
$translation_set = $form_state['values']['translation_set'];
|
92
|
|
93
|
switch ($form_state['values']['op']) {
|
94
|
case t('Save'):
|
95
|
$mlids = array_filter($form_state['values']['translations']);
|
96
|
$translation_set->reset_translations();
|
97
|
foreach ($mlids as $lang => $item_name) {
|
98
|
list($menu_name, $mlid) = explode(':', $item_name);
|
99
|
$item = menu_link_load($mlid);
|
100
|
$translation_set->add_item($item, $lang);
|
101
|
}
|
102
|
$translation_set->title = !empty($form_state['values']['title']) ? $form_state['values']['title'] : '';
|
103
|
$translation_set->save(TRUE);
|
104
|
drupal_set_message(t('The item translation has been saved.'));
|
105
|
break;
|
106
|
case t('Delete'):
|
107
|
$translation_set->delete(TRUE);
|
108
|
drupal_set_message(t('The item translation has been deleted.'));
|
109
|
break;
|
110
|
}
|
111
|
|
112
|
$form_state['redirect'] = 'admin/structure/menu';
|
113
|
}
|
114
|
|
115
|
/**
|
116
|
* Return a list of menu items that are valid possible parents for the given menu item.
|
117
|
*
|
118
|
* @param $menus
|
119
|
* An array of menu names and titles, such as from menu_get_menus().
|
120
|
* @param $item
|
121
|
* The menu item or the node type for which to generate a list of parents.
|
122
|
* If $item['mlid'] == 0 then the complete tree is returned.
|
123
|
* @return
|
124
|
* An array of menu link titles keyed on the a string containing the menu name
|
125
|
* and mlid. The list excludes the given item and its children.
|
126
|
*
|
127
|
* @todo This has to be turned into a #process form element callback. The
|
128
|
* 'menu_override_parent_selector' variable is entirely superfluous.
|
129
|
*/
|
130
|
function i18n_menu_parent_options($menus, $item, $langcode) {
|
131
|
// The menu_links table can be practically any size and we need a way to
|
132
|
// allow contrib modules to provide more scalable pattern choosers.
|
133
|
// hook_form_alter is too late in itself because all the possible parents are
|
134
|
// retrieved here, unless menu_override_parent_selector is set to TRUE.
|
135
|
if (variable_get('i18n_menu_override_parent_selector', FALSE)) {
|
136
|
return array();
|
137
|
}
|
138
|
// If no menu item, create a dummy one
|
139
|
$item = $item ? $item : array('mlid' => 0);
|
140
|
// Get menus that have a language or have language for terms
|
141
|
$available_menus = array();
|
142
|
foreach (menu_load_all() as $name => $menu) {
|
143
|
if ($menu['i18n_mode'] & I18N_MODE_TRANSLATE) {
|
144
|
$available_menus[$name] = $menu;
|
145
|
}
|
146
|
elseif ($menu['i18n_mode'] & I18N_MODE_LANGUAGE && $menu['language'] == $langcode) {
|
147
|
$available_menus[$name] = $menu;
|
148
|
}
|
149
|
}
|
150
|
// Disable i18n selection, enable after the query.
|
151
|
$previous = i18n_select(FALSE);
|
152
|
$options = _i18n_menu_get_options($menus, $available_menus, $item, $langcode);
|
153
|
i18n_select($previous);
|
154
|
return $options;
|
155
|
}
|
156
|
|
157
|
/**
|
158
|
* Helper function to get the items of the given menu.
|
159
|
*/
|
160
|
function _i18n_menu_get_options($menus, $available_menus, $item, $langcode) {
|
161
|
// If the item has children, there is an added limit to the depth of valid parents.
|
162
|
if (isset($item['parent_depth_limit'])) {
|
163
|
$limit = $item['parent_depth_limit'];
|
164
|
}
|
165
|
else {
|
166
|
$limit = _menu_parent_depth_limit($item);
|
167
|
}
|
168
|
|
169
|
$options = array();
|
170
|
foreach ($menus as $menu_name => $title) {
|
171
|
if (isset($available_menus[$menu_name])) {
|
172
|
if ($tree = i18n_menu_tree_all_data($menu_name, $langcode, NULL)) {
|
173
|
$options[$menu_name . ':0'] = '<' . $title . '>';
|
174
|
_menu_parents_recurse($tree, $menu_name, '--', $options, $item['mlid'], $limit);
|
175
|
}
|
176
|
}
|
177
|
}
|
178
|
return $options;
|
179
|
}
|
180
|
|
181
|
/**
|
182
|
* Filter out menu items that have a different language
|
183
|
*/
|
184
|
function i18n_menu_tree_all_data($menu_name, $langcode, $link = NULL, $max_depth = NULL) {
|
185
|
$tree = menu_tree_all_data($menu_name, $link, $max_depth);
|
186
|
return _i18n_menu_tree_filter_items($tree, $langcode);
|
187
|
}
|
188
|
|
189
|
/**
|
190
|
* Filter out menu items that have a different language
|
191
|
*/
|
192
|
function _i18n_menu_tree_filter_items($tree, $langcode) {
|
193
|
$result = array();
|
194
|
foreach ($tree as $key => $item) {
|
195
|
$lang = i18n_object_langcode($item['link']);
|
196
|
if (!empty($item['below'])) {
|
197
|
$item['below'] = _i18n_menu_tree_filter_items($item['below'], $langcode);
|
198
|
}
|
199
|
if (!empty($item['link']['customized']) && $lang == $langcode) {
|
200
|
$result[$key] = $item;
|
201
|
}
|
202
|
elseif (!empty($item['below'])) {
|
203
|
// Keep for the tree but mark as unselectable.
|
204
|
$item['link']['title'] = '(' . $item['link']['title'] . ')';
|
205
|
$result[$key] = $item;
|
206
|
}
|
207
|
}
|
208
|
return $result;
|
209
|
}
|
210
|
|
211
|
/**
|
212
|
* Callback for menu translation tab.
|
213
|
*/
|
214
|
function i18n_menu_translation_item_overview($item, $translation_set = NULL) {
|
215
|
if ($item['i18n_tsid']) {
|
216
|
// Already part of a set, grab that set.
|
217
|
$translation_set = i18n_translation_set_load($item['i18n_tsid']);
|
218
|
$translations = $translation_set->get_translations();
|
219
|
}
|
220
|
else {
|
221
|
// We have no translation source mlid, this could be a new set, emulate that.
|
222
|
$translations = array($item['language'] => $item);
|
223
|
}
|
224
|
|
225
|
$type = variable_get('translation_language_type', LANGUAGE_TYPE_INTERFACE);
|
226
|
$header = array(t('Language'), t('Title'), t('Operations'));
|
227
|
$rows = array();
|
228
|
|
229
|
foreach (i18n_language_list() as $langcode => $language_name) {
|
230
|
$options = array();
|
231
|
if (isset($translations[$langcode])) {
|
232
|
// Existing translation in the translation set: display status.
|
233
|
$translation_item = menu_link_load($translations[$langcode]['mlid']);
|
234
|
$title = l($translation_item['link_title'], $translation_item['link_path']);
|
235
|
$path = 'admin/structure/menu/item/' . $translation_item['mlid'];
|
236
|
$options[] = l(t('edit'), $path);
|
237
|
|
238
|
if ($translation_item['mlid'] == $item['mlid']) {
|
239
|
$language_name = t('<strong>@language_name</strong> (source)', array('@language_name' => $language_name));
|
240
|
}
|
241
|
}
|
242
|
else {
|
243
|
// No such translation in the set yet: help user to create it.
|
244
|
$title = t('n/a');
|
245
|
$options[] = l(t('add translation'), 'admin/structure/menu/manage/' . $item['menu_name'] . '/add', array('query' => array('translation' => $item['mlid'], 'target' => $langcode) + drupal_get_destination()));
|
246
|
}
|
247
|
$rows[$langcode] = array(
|
248
|
'language' => $language_name,
|
249
|
'title' => $title,
|
250
|
'operations' => implode(" | ", $options)
|
251
|
);
|
252
|
}
|
253
|
|
254
|
drupal_set_title(t('Translations of menu item %title', array('%title' => $item['link_title'])), PASS_THROUGH);
|
255
|
|
256
|
$build['translation_overview'] = array(
|
257
|
'#theme' => 'table',
|
258
|
'#header' => $header,
|
259
|
'#rows' => $rows,
|
260
|
);
|
261
|
|
262
|
return $build;
|
263
|
}
|