PluginProbe
Polylang / 1.5.2
Polylang v1.5.2
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / admin / admin-nav-menu.php

admin-nav-menu.php in Polylang 1.5.2, at admin/admin-nav-menu.php

300 lines 10.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * manages custom menus translations as well as the language switcher menu item on admin side
5 *
6 * @since 1.2
7 */
8 class PLL_Admin_Nav_Menu {
9
10 /*
11 * constructor: setups filters and actions
12 *
13 * @since 1.2
14 *
15 * @param object $polylang
16 */
17 public function __construct(&$polylang) {
18 $this->model = &$polylang->model;
19 $this->options = &$polylang->options;
20 $this->theme = get_option( 'stylesheet' );
21
22 // integration in the WP menu interface
23 add_action('admin_init', array(&$this, 'admin_init')); // after Polylang upgrade
24
25 // integration with WP customizer
26 add_action('customize_register', array(&$this, 'create_nav_menu_locations'), 5);
27
28 // protection against #24802
29 add_filter('pre_insert_term', array(&$this, 'pre_insert_term'), 10, 2);
30 }
31
32 /*
33 * setups filters and terms
34 * adds the language switcher metabox and create new nav menu locations
35 *
36 * @since 1.1
37 */
38 public function admin_init(){
39 add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue_scripts'));
40 add_action('wp_update_nav_menu_item', array(&$this, 'wp_update_nav_menu_item'), 10, 2);
41 add_filter('wp_get_nav_menu_items', array(&$this, 'translate_switcher_title'));
42
43 // translation of menus based on chosen locations
44 add_filter('pre_update_option_theme_mods_' . $this->theme, array($this, 'update_nav_menu_locations'));
45 add_filter('theme_mod_nav_menu_locations', array($this, 'nav_menu_locations'), 20);
46
47 // filter _wp_auto_add_pages_to_menu by language
48 add_action('transition_post_status', array(&$this, 'auto_add_pages_to_menu'), 5, 3); // before _wp_auto_add_pages_to_menu
49
50 // FIXME is it possible to choose the order (after theme locations in WP3.5 and older) ?
51 // FIXME not displayed if Polylang is activated before the first time the user goes to nav menus http://core.trac.wordpress.org/ticket/16828
52 add_meta_box('pll_lang_switch_box', __('Language switcher', 'polylang'), array( &$this, 'lang_switch' ), 'nav-menus', 'side', 'high');
53
54 $this->create_nav_menu_locations();
55 }
56
57 /*
58 * create temporary nav menu locations (one per location and per language) for all non-default language
59 *
60 * @since 1.2
61 */
62 public function create_nav_menu_locations() {
63 global $_wp_registered_nav_menus;
64
65 if (isset($_wp_registered_nav_menus)) {
66 foreach ($_wp_registered_nav_menus as $loc => $name)
67 foreach ($this->model->get_languages_list() as $lang)
68 $arr[$loc . (pll_default_language() == $lang->slug ? '' : '___' . $lang->slug)] = $name . ' ' . $lang->name;
69
70 $_wp_registered_nav_menus = $arr;
71 }
72 }
73
74 /*
75 * language switcher metabox
76 * The checkbox and all hidden fields are important
77 * thanks to John Morris for his very interesting post http://www.johnmorrisonline.com/how-to-add-a-fully-functional-custom-meta-box-to-wordpress-navigation-menus/
78 *
79 * @since 1.1
80 */
81 public function lang_switch() {
82 global $_nav_menu_placeholder, $nav_menu_selected_id;
83 $_nav_menu_placeholder = 0 > $_nav_menu_placeholder ? $_nav_menu_placeholder - 1 : -1;?>
84
85 <div id="posttype-lang-switch" class="posttypediv">
86 <div id="tabs-panel-lang-switch" class="tabs-panel tabs-panel-active">
87 <ul id ="lang-switch-checklist" class="categorychecklist form-no-clear">
88 <li>
89 <label class="menu-item-title">
90 <input type="checkbox" class="menu-item-checkbox" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-object-id]" value="-1"> <?php _e('Language switcher', 'polylang'); ?>
91 </label>
92 <input type="hidden" class="menu-item-type" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-type]" value="custom">
93 <input type="hidden" class="menu-item-title" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-title]" value="<?php _e('Language switcher', 'polylang'); ?>">
94 <input type="hidden" class="menu-item-url" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-url]" value="#pll_switcher">
95 </li>
96 </ul>
97 </div>
98 <p class="button-controls">
99 <span class="add-to-menu">
100 <input type="submit" <?php disabled( $nav_menu_selected_id, 0 ); ?> class="button-secondary submit-add-to-menu right" value="Add to Menu" name="add-post-type-menu-item" id="submit-posttype-lang-switch">
101 <span class="spinner"></span>
102 </span>
103 </p>
104 </div><?php
105 }
106
107 /*
108 * prepares javascript to modify the language switcher menu item
109 *
110 * @since 1.1
111 */
112 public function admin_enqueue_scripts() {
113 $screen = get_current_screen();
114 if ('nav-menus' != $screen->base)
115 return;
116
117 $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
118 wp_enqueue_script('pll_nav_menu', POLYLANG_URL .'/js/nav-menu'.$suffix.'.js', array('jquery'), POLYLANG_VERSION);
119
120 // the strings for the options
121 foreach (array_reverse(PLL_Switcher::get_switcher_options('menu', 'string')) as $str)
122 $data['strings'][] = $str;
123
124 $data['strings'][] = __('Language switcher', 'polylang'); // the title
125
126 // get all language switcher menu items
127 $items = get_posts(array(
128 'numberposts' => -1,
129 'nopaging' => true,
130 'post_type' => 'nav_menu_item',
131 'fields' => 'ids',
132 'meta_key' => '_pll_menu_item'
133 ));
134
135 // the options values for the language switcher
136 $data['val'] = array();
137 foreach ($items as $item)
138 $data['val'][$item] = get_post_meta($item, '_pll_menu_item', true);
139
140 // send all these data to javascript
141 wp_localize_script('pll_nav_menu', 'pll_data', $data);
142 }
143
144 /*
145 * save our menu item options
146 *
147 * @since 1.1
148 *
149 * @param int $menu_id not used
150 * @param int $menu_item_db_id
151 */
152 public function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0 ) {
153 if (empty($_POST['menu-item-url'][$menu_item_db_id]) || $_POST['menu-item-url'][$menu_item_db_id] != '#pll_switcher')
154 return;
155
156 // security check
157 // as 'wp_update_nav_menu_item' can be called from outside WP admin
158 if ( ! current_user_can('edit_theme_options') )
159 wp_die( __( 'Cheatin&#8217; uh?' ) );
160
161 check_admin_referer( 'update-nav_menu', 'update-nav-menu-nonce' );
162
163 $options = array('hide_current' => 0,'force_home' => 0 ,'show_flags' => 0 ,'show_names' => 1); // default values
164 // our jQuery form has not been displayed
165 if (empty($_POST['menu-item-pll-detect'][$menu_item_db_id])) {
166 if (!get_post_meta($menu_item_db_id, '_pll_menu_item', true)) // our options were never saved
167 update_post_meta($menu_item_db_id, '_pll_menu_item', $options);
168 }
169 else {
170 foreach ($options as $opt => $v)
171 $options[$opt] = empty($_POST['menu-item-'.$opt][$menu_item_db_id]) ? 0 : 1;
172 update_post_meta($menu_item_db_id, '_pll_menu_item', $options); // allow us to easily identify our nav menu item
173 }
174
175 }
176
177 /*
178 * translates the language switcher menu items title in case the user switches the admin language
179 *
180 * @since 1.1.1
181 *
182 * @param array $items
183 * @return array modified $items
184 */
185 public function translate_switcher_title($items) {
186 foreach ($items as $item)
187 if ('#pll_switcher' == $item->url)
188 $item->post_title = __('Language switcher', 'polylang');
189 return $items;
190 }
191
192 /*
193 * assign menu languages and translations based on (temporary) locations
194 *
195 * @since 1.1
196 *
197 * @param array $mods theme mods
198 * @return unmodified $mods
199 */
200 public function update_nav_menu_locations($mods) {
201 if (isset($mods['nav_menu_locations'])) {
202
203 // security check
204 if ( ! current_user_can('edit_theme_options') )
205 wp_die( __( 'Cheatin&#8217; uh?' ) );
206
207 if (isset($_REQUEST['action']) && 'locations' == $_REQUEST['action']) {
208 check_admin_referer( 'save-menu-locations' );
209 $this->options['nav_menus'][$this->theme] = array();
210 }
211
212 elseif (isset($_REQUEST['action']) && 'update' == $_REQUEST['action']) {
213 check_admin_referer( 'update-nav_menu', 'update-nav-menu-nonce' );
214 $this->options['nav_menus'][$this->theme] = array();
215 }
216
217 // customizer
218 // don't reset locations in this case.
219 // see http://wordpress.org/support/topic/menus-doesnt-show-and-not-saved-in-theme-settings-multilingual-site
220 elseif (isset($_REQUEST['action']) && 'customize_save' == $_REQUEST['action']) {
221 check_ajax_referer( 'save-customize_' . $GLOBALS['wp_customize']->get_stylesheet(), 'nonce' );
222 }
223
224 else
225 return; // not called from WP
226
227 $default = pll_default_language();
228
229 // extract language and menu from locations
230 foreach ($mods['nav_menu_locations'] as $loc => $menu) {
231 if ($pos = strpos($loc, '___')) {
232 $this->options['nav_menus'][$this->theme][substr($loc, 0, $pos)][substr($loc, $pos+3)] = $menu;
233 unset($mods['nav_menu_locations'][$loc]); // remove temporary locations before database update
234 }
235 else
236 $this->options['nav_menus'][$this->theme][$loc][$default] = $menu;
237 }
238
239 update_option('polylang', $this->options);
240 }
241 return $mods;
242 }
243
244 /*
245 * fills temporary menu locations based on menus translations
246 *
247 * @since 1.2
248 *
249 * @param bool|array $menus
250 * @return bool|array modified list of menu locations
251 */
252 public function nav_menu_locations($menus) {
253 if (is_array($menus)) {
254 foreach ($menus as $loc => $menu) {
255 foreach ($this->model->get_languages_list() as $lang) {
256 if (pll_default_language() != $lang->slug && !empty($this->options['nav_menus'][$this->theme][$loc][$lang->slug]))
257 $menus[$loc . '___' . $lang->slug] = $this->options['nav_menus'][$this->theme][$loc][$lang->slug];
258 }
259 }
260 }
261
262 return $menus;
263 }
264
265 /*
266 * filters _wp_auto_add_pages_to_menu by language
267 *
268 * @since 0.9.4
269 *
270 * @param string $new_status Transition to this post status.
271 * @param string $old_status Previous post status.
272 * @param object $post Post data.
273 */
274 public function auto_add_pages_to_menu( $new_status, $old_status, $post ) {
275 if ('publish' != $new_status || 'publish' == $old_status || 'page' != $post->post_type || ! empty($post->post_parent) || !($lang = $this->model->get_post_language($post->ID)))
276 return;
277
278 // get all the menus in the post language
279 $menus = get_terms('nav_menu', array('lang' => $lang->slug, 'fields' => 'ids', 'hide_empty' => false));
280 $menus = implode(',', $menus);
281
282 add_filter('option_nav_menu_options', create_function('$a', "\$a['auto_add'] = array_intersect(\$a['auto_add'], array($menus)); return \$a;"));
283 }
284
285 /*
286 * FIXME prevents sharing a menu term with a language term by renaming the nav menu before its creation
287 * to avoid http://core.trac.wordpress.org/ticket/24802
288 * and http://wordpress.org/support/topic/all-connection-between-elements-lost
289 *
290 * @since 1.1.3
291 *
292 * @param string $name term name
293 * @param string $taxonomy
294 * @return string modified (nav menu) term name if necessary
295 */
296 function pre_insert_term($name, $taxonomy) {
297 return ('nav_menu' == $taxonomy && in_array($name, $this->model->get_languages_list(array('fields' => 'name')))) ? $name .= '-menu' : $name;
298 }
299 }
300