PluginProbe
Polylang / 0.3.1
Polylang v0.3.1
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.php

admin.php in Polylang 0.3.1, at admin.php

602 lines 21.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 require_once(POLYLANG_DIR.'/list-table.php');
4 define('POLYLANG_URL', WP_PLUGIN_URL .'/polylang');
5
6 class Polylang_Admin extends Polylang_Base {
7 function __construct() {
8 add_action('admin_init', array(&$this, 'admin_init'));
9
10 // adds a 'settings' link in the plugins table
11 $plugin_file = basename( dirname( __FILE__ ) ).'/polylang.php';
12 add_filter('plugin_action_links_'.$plugin_file, array(&$this, 'plugin_action_links'));
13
14 // adds the link to the languages panel in the wordpress admin menu
15 add_action('admin_menu', array(&$this, 'add_menus'));
16
17 // setup js scripts
18 add_action('admin_print_scripts', array($this,'admin_js'));
19
20 // add the language column (as well as a filter by language) in 'All Posts' an 'All Pages' panels
21 add_filter('manage_posts_columns', array(&$this, 'add_post_column'), 10, 2);
22 add_filter('manage_pages_columns', array(&$this, 'add_post_column'));
23 add_action('manage_posts_custom_column', array(&$this, 'post_column'), 10, 2);
24 add_action('manage_pages_custom_column', array(&$this, 'post_column'), 10, 2);
25 add_filter('parse_query',array(&$this,'parse_query'));
26 add_action('restrict_manage_posts', array(&$this, 'restrict_manage_posts'));
27
28 // adds the Languages box in the 'Edit Post' and 'Edit Page' panels
29 add_action('add_meta_boxes', array(&$this, 'add_meta_boxes'));
30
31 // ajax response for post metabox
32 add_action('wp_ajax_post_lang_choice', array($this,'post_lang_choice'));
33
34 // adds actions related to languages when saving aor deleting posts and pages
35 add_action('save_post', array(&$this, 'save_post'));
36 add_action('before_delete_post', array(&$this, 'delete_post'));
37
38 // adds the language field in the 'Categories' and 'Post Tags' panels
39 add_action('category_add_form_fields', array(&$this, 'add_term_form'));
40 add_action('post_tag_add_form_fields', array(&$this, 'add_term_form'));
41
42 // adds the language field and translations tables in the 'Edit Category' and 'Edit Tag' panels
43 add_action('category_edit_form_fields', array(&$this, 'edit_term_form'));
44 add_action('post_tag_edit_form_fields', array(&$this, 'edit_term_form'));
45
46 // ajax response for edit term form
47 add_action('wp_ajax_term_lang_choice', array($this,'term_lang_choice'));
48
49 // adds the language column in the 'Categories' and 'Post Tags' tables
50 add_filter('manage_edit-category_columns', array(&$this, 'add_term_column'));
51 add_filter('manage_edit-post_tag_columns', array(&$this, 'add_term_column'));
52 add_action('manage_category_custom_column', array(&$this, 'term_column'), 10, 3);
53 add_action('manage_post_tag_custom_column', array(&$this, 'term_column'), 10, 3);
54
55 // adds actions related to languages when saving or deleting categories and post tags
56 add_action('created_category', array(&$this, 'save_term'));
57 add_action('created_post_tag', array(&$this, 'save_term'));
58 add_action('edited_category', array(&$this, 'save_term'));
59 add_action('edited_post_tag', array(&$this, 'save_term'));
60 add_action('delete_category', array(&$this, 'delete_term'));
61 add_action('delete_post_tag', array(&$this, 'delete_term'));
62
63 // modifies the theme location nav menu metabox
64 add_filter('admin_head-nav-menus.php', array(&$this, 'nav_menu_theme_locations'));
65
66 // widgets languages filter
67 add_action('in_widget_form', array(&$this, 'in_widget_form'));
68 add_filter('widget_update_callback', array(&$this, 'widget_update_callback'), 10, 4);
69
70 // refresh rewrite rules if the 'page_on_front' option is modified
71 add_action('update_option', array(&$this, 'update_option'));
72 }
73
74 // manage versions
75 // not very useful now but we don't know the future
76 function admin_init() {
77 $options = get_option('polylang');
78 if ($options['version'] < POLYLANG_VERSION) {
79 $options['version'] = POLYLANG_VERSION;
80 update_option('polylang', $options);
81 }
82 }
83
84 // adds a 'settings' link in the plugins table
85 function plugin_action_links($links) {
86 $settings_link = '<a href="admin.php?page=mlang">' . __('Settings') . '</a>';
87 array_unshift( $links, $settings_link );
88 return $links;
89 }
90
91 // adds the link to the languages panel in the wordpress admin menu
92 function add_menus() {
93 add_submenu_page('options-general.php', __('Languages','polylang'), __('Languages','polylang'), 'manage_options', 'mlang', array($this, 'languages_page'));
94 }
95
96 // setup js scripts
97 function admin_js() {
98 wp_enqueue_script('polylang_admin', POLYLANG_URL.'/admin.js');
99 }
100
101 // the languages panel
102 function languages_page() {
103 global $wp_rewrite;
104 $options = get_option('polylang');
105
106 $listlanguages = $this->get_languages_list();
107 $list_table = new Polylang_List_Table();
108
109 // for nav menus form
110 $locations = get_registered_nav_menus();
111 $menus = wp_get_nav_menus();
112 $menu_lang = get_option('polylang_nav_menus');
113
114 $action = '';
115 if (isset($_REQUEST['action']))
116 $action = $_REQUEST['action'];
117
118 switch ($action) {
119 case 'add':
120 check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
121
122 // FIXME improve data validation
123 // FIXME add an error message if conditions are not fulfilled
124 if ($_POST['name'] && $_POST['description'] && $_POST['slug']) {
125 wp_insert_term($_POST['name'],'language',array('slug'=>$_POST['slug'], 'description'=>$_POST['description']));
126 $wp_rewrite->flush_rules(); // refresh rewrite rules
127
128 if (!isset($options['default_lang'])) { // if this is the first language created, set it as default language
129 $options['default_lang'] = $_POST['slug'];
130 update_option('polylang', $options);
131 }
132 }
133 wp_redirect('admin.php?page=mlang'); // to refresh the page (possible thanks to the $_GET['noheader']=true)
134 exit;
135 break;
136
137 case 'delete':
138 check_admin_referer( 'delete-lang');
139
140 if (isset($_GET['lang']) && $_GET['lang']) {
141 $lang_id = (int) $_GET['lang'];
142 $lang = $this->get_language($lang_id);
143 $lang_slug = $lang->slug;
144
145 // delete all translations in posts in this language
146 $args = array('numberposts'=>-1, 'taxonomy' => 'language', 'term' => $lang_slug, 'post_type'=>'any', 'post_status'=>'any');
147 $posts = get_posts($args);
148 foreach ($posts as $post) {
149 foreach ($languages as $language) {
150 delete_post_meta($post->ID, '_lang-'.$language->slug);
151 }
152 }
153
154 // delete references to this language in all posts
155 $args = array('numberposts'=>-1, 'meta_key'=>'_lang-'.$lang_slug, 'post_type'=>'any', 'post_status'=>'any');
156 $posts = get_posts($args);
157 foreach ($posts as $post) {
158 delete_post_meta($post->ID, '_lang-'.$lang_slug);
159 }
160
161 // delete references to this language in categories & post tags
162 $terms = get_terms(array('category', 'post_tag'), 'get=all');
163 foreach ($terms as $term) {
164 if ($this->get_term_language($term->term_id) == $lang) {
165 foreach ($languages as $language) {
166 delete_metadata('term', $term->term_id, '_lang-'.$language->slug); // deletes translations of this term
167 }
168 delete_metadata('term', $term->term_id, '_language', $lang_id); // delete language of this term
169 }
170 delete_metadata('term', $term->term_id, '_lang-'.$lang_slug); // deletes references to this term in translated term
171 }
172
173 // delete the language itself
174 wp_delete_term($lang_id, 'language');
175 $wp_rewrite->flush_rules(); // refresh rewrite rules
176
177 // oops ! we deleted the default language...
178 if ($options['default_lang'] == $lang_slug) {
179 if (!empty($languages))
180 $options['default_lang'] = $languages[0]->slug; // arbitrary choice...
181 else
182 unset($options['default_lang']);
183 update_option('polylang', $options);
184 }
185 }
186 wp_redirect('admin.php?page=mlang'); // to refresh the page (possible thanks to the $_GET['noheader']=true)
187 exit;
188 break;
189
190 case 'edit':
191 if (isset($_GET['lang']) && $_GET['lang'])
192 $edit_lang = $this->get_language((int) $_GET['lang']);
193 break;
194
195 case 'update':
196 check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
197
198 // FIXME add an error message if conditions are not fulfilled
199 if ($_POST['lang'] && $_POST['name'] && $_POST['description'] && $_POST['slug']) {
200 // Update links to this language in posts and terms in case the slug has been modified
201 $lang_id = (int) $_POST['lang'];
202 $lang = $this->get_language($lang_id);
203 $old_slug = $lang->slug;
204
205 if ($old_slug != $_POST['slug']) {
206 // update the language slug in posts meta
207 $args = array('numberposts'=>-1, 'meta_key'=>'_lang-'.$old_slug, 'post_type'=>'any', 'post_status'=>'any');
208 $posts = get_posts($args);
209 foreach ($posts as $post) {
210 $post_id = get_post_meta($post->ID, '_lang-'.$old_slug, true);
211 delete_post_meta($post->ID, '_lang-'.$old_slug);
212 update_post_meta($post->ID, '_lang-'.$_POST['slug'], $post_id);
213 }
214
215 // update the language slug in categories & post tags meta
216 $terms = get_terms(array('category', 'post_tag'), 'get=all');
217 foreach ($terms as $term) {
218 $term_id = get_metadata('term', $term->term_id, '_lang-'.$old_slug, true);
219 if ($term_id) {
220 delete_metadata('term', $term->term_id, '_lang-'.$old_slug);
221 update_metadata('term', $term->term_id, '_lang-'.$_POST['slug'], $term_id);
222 }
223 }
224 }
225
226 // and finally update the language itself
227 wp_update_term($lang_id, 'language', array('name'=>$_POST['name'], 'slug'=>$_POST['slug'], 'description'=>$_POST['description']));
228 $wp_rewrite->flush_rules(); // refresh rewrite rules
229 }
230 wp_redirect('admin.php?page=mlang'); // to refresh the page (possible thanks to the $_GET['noheader']=true)
231 exit;
232 break;
233
234 case 'nav-menus':
235 check_admin_referer( 'nav-menus-lang', '_wpnonce_nav-menus-lang' );
236
237 $menu_lang = $_POST['menu-lang'];
238 update_option('polylang_nav_menus', $menu_lang);
239 break;
240
241 case 'options':
242 check_admin_referer( 'options-lang', '_wpnonce_options-lang' );
243
244 $options['rewrite'] = $_POST['rewrite'];
245 isset($_POST['browser']) ? $options['browser'] = 1 : $options['browser'] = 0;
246 $options['default_lang'] = $_POST['default_lang'];
247 update_option('polylang', $options);
248
249 // refresh refresh permalink structure and rewrite rules in case rewrite option has been modified
250 $wp_rewrite->extra_permastructs['language'][0] = $options['rewrite'] ? '%language%' : '/language/%language%';
251 $wp_rewrite->flush_rules();
252 break;
253
254 default:
255 }
256
257 // prepare the list table of languages
258 $data = array();
259 foreach ($listlanguages as $lang)
260 $data[] = (array) $lang;
261
262 $list_table->prepare_items($data);
263
264 // displays the page
265 include(POLYLANG_DIR.'/languages-form.php');
266 }
267
268 // adds the language column (before the date column) in the posts and pages list table
269 function add_post_column($columns, $post_type ='') {
270 if (in_array($post_type, array('', 'post', 'page'))) {
271 $keys = array( 'date', 'comments' );
272 foreach ($keys as $k) {
273 if (array_key_exists($k, $columns))
274 $end[$k] = array_pop($columns);
275 }
276
277 $columns['language'] = __('Language', 'polylang');
278
279 if (isset($end))
280 $columns = array_merge($columns, $end);
281 }
282 return $columns;
283 }
284
285 // fills the language column in the posts table
286 function post_column($column, $post_id) {
287 $lang = $this->get_post_language($post_id);
288 if ($lang && $column == 'language')
289 echo esc_attr($lang->name);
290 }
291
292 // converts language term_id to slug in $query
293 // needed to filter the posts by language with wp_dropdown_categories in restrict_manage_posts
294 function parse_query($query) {
295 global $pagenow;
296 $qvars = &$query->query_vars;
297 if ($pagenow=='edit.php' && isset($qvars['lang']) && $qvars['lang'] && is_numeric($qvars['lang'])) {
298 $lang = $this->get_language($qvars['lang']);
299 if ($lang)
300 $qvars['lang'] = $lang->slug;
301 }
302 }
303
304 // adds a filter for languages in the Posts and Pages panels
305 function restrict_manage_posts() {
306 global $wp_query;
307 $screen = get_current_screen();
308 $languages = $this->get_languages_list();
309
310 if (!empty($languages) && $screen->base == 'edit') {
311 $qvars = $wp_query->query;
312 wp_dropdown_categories(array(
313 'show_option_all' => __('Show all languages', 'polylang'),
314 'name' => 'lang',
315 'selected' => isset($qvars['lang']) ? $qvars['lang'] : 0,
316 'taxonomy' => 'language'));
317 }
318 }
319
320 // adds the Languages box in the 'Edit Post' and 'Edit Page' panels
321 function add_meta_boxes() {
322 add_meta_box('ml_box', __('Languages','polylang'), array(&$this,'post_language'), 'post', 'side','high');
323 add_meta_box('ml_box', __('Languages','polylang'), array(&$this,'post_language'), 'page', 'side','high');
324 }
325
326 // the Languages metabox in the 'Edit Post' and 'Edit Page' panels
327 function post_language() {
328 global $post_ID;
329 $post_type = get_post_type($post_ID);
330
331 $lang = $this->get_post_language($post_ID);
332 if (isset($_GET['new_lang']))
333 $lang = $this->get_language($_GET['new_lang']);
334
335 $listlanguages = $this->get_languages_list();
336
337 include(POLYLANG_DIR.'/post-metabox.php');
338 }
339
340 // ajax response for post metabox
341 function post_lang_choice() {
342 $listlanguages = $this->get_languages_list();
343
344 $lang = $this->get_language($_POST['lang']);
345 $post_ID = $_POST['post_id'];
346
347 if ($lang)
348 include(POLYLANG_DIR.'/post-translations.php');
349
350 die();
351 }
352
353 // called when a post (or page) is saved, published or updated
354 // the underscore in '_lang' hides the post meta in the Custom Fields metabox in the Edit Post screen
355 function save_post($post_id) {
356
357 $id = wp_is_post_revision($post_id);
358 if ($id)
359 $post_id = $id;
360
361 if (isset($_POST['post_lang_choice']))
362 wp_set_post_terms($post_id, $_POST['post_lang_choice'], 'language' );
363
364 $lang = $this->get_post_language($post_id);
365 $listlanguages = $this->get_languages_list();
366
367 foreach ($listlanguages as $language) {
368
369 if (isset($_POST[$language->slug]) && $_POST[$language->slug]) {
370 // FIXME I don't check that the translated post is in the right language !
371 update_post_meta($post_id, '_lang-'.$language->slug, $_POST[$language->slug]); // saves the links to translated posts
372 if ($lang)
373 update_post_meta($this->get_translated_post($post_id, $language), '_lang-'.$lang->slug, $post_id); // tells the translated to link to this post
374 }
375 else {
376 // deletes the translation in case there was previously one
377 if ($lang)
378 delete_post_meta($this->get_translated_post($post_id, $language), '_lang-'.$lang->slug); // in the translated post
379 delete_post_meta($post_id, '_lang-'.$language->slug); // in this post
380 }
381 }
382
383 // propagates translations between them
384 foreach ($listlanguages as $language) {
385 foreach ($listlanguages as $lg) {
386 $id = $this->get_translated_post($post_id, $lg);
387 if ($lg != $lang && $lg != $language && $id)
388 update_post_meta($this->get_translated_post($post_id, $language), '_lang-'.$lg->slug, $id);
389 }
390 }
391 }
392
393 // called when a post (or page) is deleted
394 function delete_post($post_id) {
395 $id = wp_is_post_revision($post_id);
396 if ($id)
397 $post_id = $id;
398
399 $lang = $this->get_post_language($post_id);
400 if($lang) {
401 $listlanguages = $this->get_languages_list();
402 foreach ($listlanguages as $language) {
403 delete_post_meta($this->get_translated_post($post_id, $language), '_lang-'.$lang->slug); // delete links to this post
404 // WP deletes post metas linked to this post so it is useless to do it before
405 }
406 }
407 }
408
409 // adds the language field in the 'Categories' and 'Post Tags' panels
410 function add_term_form() {
411 $taxonomy = $_GET['taxonomy'];
412 $lang = null;
413 if (isset($_GET['new_lang']))
414 $lang = $this->get_language($_GET['new_lang']);
415
416 $listlanguages = $this->get_languages_list();
417
418 // displays the language field
419 include(POLYLANG_DIR.'/add-term-form.php');
420 }
421
422 // adds the language field and translations tables in the 'Edit Category' and 'Edit Tag' panels
423 function edit_term_form($tag) {
424 $term_id = $tag->term_id;
425 $lang = $this->get_term_language($term_id);
426 $taxonomy = $tag->taxonomy;
427 $listlanguages = $this->get_languages_list();
428
429 include(POLYLANG_DIR.'/edit-term-form.php');
430 }
431
432 // ajax response for edit term form
433 function term_lang_choice()
434 {
435 if ($_POST['lang']) {
436 $lang = $this->get_language($_POST['lang']);
437 $term_id = isset($_POST['term_id']) ? $_POST['term_id'] : null;
438 $taxonomy = $_POST['taxonomy'];
439
440 $listlanguages = $this->get_languages_list();
441
442 include(POLYLANG_DIR.'/term-translations.php');
443 }
444 die();
445 }
446
447 // adds the language column (before the posts column) in the 'Categories' or Post Tags table
448 function add_term_column($columns) {
449 if (array_key_exists('posts', $columns))
450 $end = array_pop($columns);
451
452 $columns['language'] = __('Language', 'polylang');
453
454 if (isset($end))
455 $columns['posts'] = $end;
456
457 return $columns;
458 }
459
460 // fills the language column in the 'Categories' or Post Tags table
461 function term_column($empty, $column, $term_id) {
462 $lang = $this->get_term_language($term_id);
463 if ($lang && $column == 'language')
464 echo esc_attr($lang->name);
465 }
466
467 // called when a category or post tag is created or edited
468 function save_term($term_id) {
469
470 if (isset($_POST['term_lang_choice']) && $_POST['term_lang_choice'])
471 update_metadata('term', $term_id, '_language', $_POST['term_lang_choice'] );
472 else
473 delete_metadata('term', $term_id, '_language');
474
475
476 $lang = $this->get_term_language($term_id);
477 $listlanguages = $this->get_languages_list();
478
479 foreach ($listlanguages as $language) {
480 $slug = '_lang-'.$language->slug;
481 if (isset($_POST[$slug]) && $_POST[$slug]) {
482 // FIXME I don't check that the translated term is in the right language !
483 update_metadata('term', $term_id, $slug, $_POST[$slug] );
484 if ($lang)
485 update_metadata('term', $_POST[$slug], '_lang-'.$lang->slug, $term_id );
486 }
487 else {
488 // deletes the translation in case there was previously one
489 if ($lang)
490 delete_metadata('term', $this->get_translated_term($term_id, $language), '_lang-'.$lang->slug); // in the translated term
491 delete_metadata('term', $term_id, '_lang-'.$language->slug); // in this term
492 }
493
494 }
495
496 // propagates translations between them
497 if (isset($lang)) {
498 foreach ($listlanguages as $language) {
499 foreach ($listlanguages as $lg) {
500 $id = $this->get_translated_term($term_id, $lg);
501 if ($lg != $lang && $lg != $language && $id)
502 update_metadata('term',$this->get_translated_term($term_id, $language), '_lang-'.$lg->slug, $id);
503 }
504 }
505 }
506
507 }
508
509 // called when a category or post tag is deleted
510 function delete_term($term_id) {
511 $lang = $this->get_term_language($term_id);
512 if($lang) {
513 delete_metadata('term', $term_id, '_language' );
514 $listlanguages = $this->get_languages_list();
515 foreach ($listlanguages as $language) {
516 delete_metadata('term', $this->get_translated_term($term_id, $language), '_lang-'.$lang->slug); // delete links to this term
517 }
518 foreach ($listlanguages as $language) {
519 delete_metadata('term', $term_id, '_lang-'.$language->slug);
520 }
521 }
522 }
523
524 // returns all terms in the $taxonomy in the $term_language which have no translation in the $translation_language
525 function get_terms_not_translated($taxonomy, $term_language, $translation_language) {
526 $new_terms = array();
527 $terms = get_terms($taxonomy, 'hide_empty=0');
528 foreach ($terms as $term) {
529 $lang = $this->get_term_language($term->term_id);
530 if ($lang && $lang->name == $term_language->name) {
531 $translated_term = $this->get_translated_term($term->term_id, $translation_language);
532 if (!$translated_term)
533 $new_terms[] = $term;
534 }
535 }
536 return $new_terms;
537 }
538
539 // modifies the theme location nav menu metabox
540 function nav_menu_theme_locations() {
541 // only if the theme supports nav menus
542 if ( ! current_theme_supports( 'menus' ) )
543 return;
544
545 // thanks to : http://wordpress.stackexchange.com/questions/2770/how-to-add-a-custom-metabox-to-the-menu-management-admin-screen
546 $metabox = &$GLOBALS['wp_meta_boxes']['nav-menus']['side']['default']['nav-menu-theme-locations'];
547 $metabox['callback'] = array(&$this,'nav_menu_language');
548 $metabox['title'] = __('Theme locations and languages', 'polylang');
549 }
550
551 // displays a message to redirect to the languages options page
552 function nav_menu_language() {
553 echo '<p class="howto">' . sprintf (__('Please go to the %slanguages page%s to set theme locations and languages', 'polylang'),
554 '<a href="' . admin_url('options-general.php?page=mlang#menus') . '">', '</a>') . '</p>';
555 }
556
557 // modifies the widgets forms to add our language dropdwown list
558 function in_widget_form($widget) {
559 $id = esc_attr($widget->id.'_lang_choice');
560 $listlanguages = $this->get_languages_list();
561 $widget_lang = get_option('polylang_widgets');
562
563 printf(
564 '<p><label for="%s">%s<select name="%s" id="%s" class="tags-input"><option value="0">%s</option>',
565 $id,
566 __('The widget is displayed for:', 'polylang'),
567 $id,
568 $id,
569 __('All languages', 'polylang')
570 );
571 foreach ($listlanguages as $language) {
572 printf(
573 "<option value='%s'%s>%s</option>\n",
574 esc_attr($language->slug),
575 $language->slug == $widget_lang[$widget->id] ? ' selected="selected"' : '',
576 esc_attr($language->name)
577 );
578 }
579 echo '</select></label></p>';
580 }
581
582 // called when widget options are saved
583 function widget_update_callback($instance, $new_instance, $old_instance, $widget) {
584 $id = $widget->id.'_lang_choice';
585 if (isset($_POST[$id]) && $_POST[$id]) {
586 $widget_lang = get_option('polylang_widgets');
587 $widget_lang[$widget->id] = $_POST[$id];
588 update_option('polylang_widgets', $widget_lang);
589 }
590 return $instance;
591 }
592
593 // refresh rewrite rules if the 'page_on_front' option is modified
594 function update_option($option) {
595 global $wp_rewrite;
596 if ($option == 'page_on_front')
597 $wp_rewrite->flush_rules();
598 }
599 } // class Polylang_Admin
600
601 ?>
602