PluginProbe
Polylang / 1.6
Polylang v1.6
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.6, at admin/admin-nav-menu.php

297 lines 10.8 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 check_admin_referer( 'update-nav_menu', 'update-nav-menu-nonce' );
160
161 $options = array('hide_current' => 0,'force_home' => 0 ,'show_flags' => 0 ,'show_names' => 1); // default values
162 // our jQuery form has not been displayed
163 if (empty($_POST['menu-item-pll-detect'][$menu_item_db_id])) {
164 if (!get_post_meta($menu_item_db_id, '_pll_menu_item', true)) // our options were never saved
165 update_post_meta($menu_item_db_id, '_pll_menu_item', $options);
166 }
167 else {
168 foreach ($options as $opt => $v)
169 $options[$opt] = empty($_POST['menu-item-'.$opt][$menu_item_db_id]) ? 0 : 1;
170 update_post_meta($menu_item_db_id, '_pll_menu_item', $options); // allow us to easily identify our nav menu item
171 }
172 }
173 }
174
175 /*
176 * translates the language switcher menu items title in case the user switches the admin language
177 *
178 * @since 1.1.1
179 *
180 * @param array $items
181 * @return array modified $items
182 */
183 public function translate_switcher_title($items) {
184 foreach ($items as $item)
185 if ('#pll_switcher' == $item->url)
186 $item->post_title = __('Language switcher', 'polylang');
187 return $items;
188 }
189
190 /*
191 * assign menu languages and translations based on (temporary) locations
192 *
193 * @since 1.1
194 *
195 * @param array $mods theme mods
196 * @return unmodified $mods
197 */
198 public function update_nav_menu_locations($mods) {
199 if (current_user_can('edit_theme_options') && isset($mods['nav_menu_locations'])) {
200
201 // Manage Locations tab in Appearance -> Menus
202 if (isset($_REQUEST['action']) && 'locations' == $_REQUEST['action']) {
203 check_admin_referer('save-menu-locations');
204 $this->options['nav_menus'][$this->theme] = array();
205 }
206
207 // Edit Menus tab in Appearance -> Menus
208 // add the test of $_REQUEST['update-nav-menu-nonce'] to avoid conflict with Vantage theme
209 elseif (isset($_REQUEST['action'], $_REQUEST['update-nav-menu-nonce']) && 'update' == $_REQUEST['action']) {
210 check_admin_referer('update-nav_menu', 'update-nav-menu-nonce');
211 $this->options['nav_menus'][$this->theme] = array();
212 }
213
214 // customizer
215 // don't reset locations in this case.
216 // see http://wordpress.org/support/topic/menus-doesnt-show-and-not-saved-in-theme-settings-multilingual-site
217 elseif (isset($_REQUEST['action']) && 'customize_save' == $_REQUEST['action']) {
218 check_ajax_referer( 'save-customize_' . $GLOBALS['wp_customize']->get_stylesheet(), 'nonce' );
219 }
220
221 else
222 return $mods; // no modification for nav menu locations
223
224 $default = pll_default_language();
225
226 // extract language and menu from locations
227 foreach ($mods['nav_menu_locations'] as $loc => $menu) {
228 if ($pos = strpos($loc, '___')) {
229 $this->options['nav_menus'][$this->theme][substr($loc, 0, $pos)][substr($loc, $pos+3)] = $menu;
230 unset($mods['nav_menu_locations'][$loc]); // remove temporary locations before database update
231 }
232 else
233 $this->options['nav_menus'][$this->theme][$loc][$default] = $menu;
234 }
235
236 update_option('polylang', $this->options);
237 }
238 return $mods;
239 }
240
241 /*
242 * fills temporary menu locations based on menus translations
243 *
244 * @since 1.2
245 *
246 * @param bool|array $menus
247 * @return bool|array modified list of menu locations
248 */
249 public function nav_menu_locations($menus) {
250 if (is_array($menus)) {
251 foreach ($menus as $loc => $menu) {
252 foreach ($this->model->get_languages_list() as $lang) {
253 if (pll_default_language() != $lang->slug && !empty($this->options['nav_menus'][$this->theme][$loc][$lang->slug]))
254 $menus[$loc . '___' . $lang->slug] = $this->options['nav_menus'][$this->theme][$loc][$lang->slug];
255 }
256 }
257 }
258
259 return $menus;
260 }
261
262 /*
263 * filters _wp_auto_add_pages_to_menu by language
264 *
265 * @since 0.9.4
266 *
267 * @param string $new_status Transition to this post status.
268 * @param string $old_status Previous post status.
269 * @param object $post Post data.
270 */
271 public function auto_add_pages_to_menu( $new_status, $old_status, $post ) {
272 if ('publish' != $new_status || 'publish' == $old_status || 'page' != $post->post_type || ! empty($post->post_parent) || !($lang = $this->model->get_post_language($post->ID)))
273 return;
274
275 // get all the menus in the post language
276 $menus = get_terms('nav_menu', array('lang' => $lang->slug, 'fields' => 'ids', 'hide_empty' => false));
277 $menus = implode(',', $menus);
278
279 add_filter('option_nav_menu_options', create_function('$a', "\$a['auto_add'] = array_intersect(\$a['auto_add'], array($menus)); return \$a;"));
280 }
281
282 /*
283 * FIXME prevents sharing a menu term with a language term by renaming the nav menu before its creation
284 * to avoid http://core.trac.wordpress.org/ticket/24802
285 * and http://wordpress.org/support/topic/all-connection-between-elements-lost
286 *
287 * @since 1.1.3
288 *
289 * @param string $name term name
290 * @param string $taxonomy
291 * @return string modified (nav menu) term name if necessary
292 */
293 function pre_insert_term($name, $taxonomy) {
294 return ('nav_menu' == $taxonomy && in_array($name, $this->model->get_languages_list(array('fields' => 'name')))) ? $name .= '-menu' : $name;
295 }
296 }
297