Polylang - Version 1.7.3

Version Description

(2015-04-11) =

  • the transient 'pll_languages_list' now stores an array of arrays instead of an array of PLL_Language objects
  • fix: fatal error for users hosted at GoDaddy (due to PLL_Language objects stored in a transient)
  • fix: additional query vars are removed from home page
  • fix: categories are not filtered by the admin language switcher in posts list table (introduced in 1.7)
  • fix: when using multiple domains, the domain url is lost when modifying the language slug
  • fix: the queried object is incorrectly set for author archives (introduced in 1.6.5)
  • fix: notice when a nav menu assigned to a translated nav menu location has been deleted
  • fix: no canonical redirection when using pretty permalinks and querying default permalinks
Download this release

Release Info

Developer Chouby
Plugin Icon 128x128 Polylang
Version 1.7.3
Comparing to
See all releases

Code changes from version 1.7.2 to 1.7.3

admin/admin-filters-columns.php CHANGED
@@ -205,14 +205,19 @@ class PLL_Admin_Filters_Columns {
205
 
206
  $post_type = isset($GLOBALS['post_type']) ? $GLOBALS['post_type'] : $_REQUEST['post_type']; // 2nd case for quick edit
207
  $taxonomy = isset($GLOBALS['taxonomy']) ? $GLOBALS['taxonomy'] : $_REQUEST['taxonomy'];
 
 
 
 
 
208
  $language = $this->model->get_language(substr($column, 9));
209
 
210
  if ($column == $this->get_first_language_column()) {
211
- $out = sprintf('<div class="hidden" id="lang_%d">%s</div>', esc_attr($term_id), esc_html($lang->slug));
212
 
213
  // identify the default categories to disable the language dropdown in js
214
  if (in_array(get_option('default_category'), $this->model->get_translations('term', $term_id)))
215
- $out .= sprintf('<div class="hidden" id="default_cat_%1$d">%1$d</div>', esc_attr($term_id));
216
  }
217
 
218
  // link to edit term (or a translation)
@@ -248,9 +253,12 @@ class PLL_Admin_Filters_Columns {
248
  $x = new WP_Ajax_Response();
249
  $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );
250
 
251
- $post_type = $_POST['post_type'];
 
 
252
  $translations = empty($_POST['translations']) ? array() : explode(',', $_POST['translations']); // collect old translations
253
  $translations = array_merge($translations, array($_POST['post_id'])); // add current post
 
254
 
255
  foreach ($translations as $post_id) {
256
  $level = is_post_type_hierarchical( $post_type ) ? count( get_ancestors( $post_id, $post_type ) ) : 0;
@@ -278,10 +286,13 @@ class PLL_Admin_Filters_Columns {
278
  $x = new WP_Ajax_Response();
279
  $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) );
280
 
281
- $taxonomy = $_POST['taxonomy'];
 
 
282
  $translations = empty($_POST['translations']) ? array() : explode(',', $_POST['translations']); // collect old translations
283
- $translations = array_merge($translations, $this->model->get_translations('term', $_POST['term_id'])); // add current translations
284
  $translations = array_unique($translations); // remove doublons
 
285
 
286
  foreach ($translations as $term_id) {
287
  $level = is_taxonomy_hierarchical($taxonomy) ? count( get_ancestors( $term_id, $taxonomy ) ) : 0;
205
 
206
  $post_type = isset($GLOBALS['post_type']) ? $GLOBALS['post_type'] : $_REQUEST['post_type']; // 2nd case for quick edit
207
  $taxonomy = isset($GLOBALS['taxonomy']) ? $GLOBALS['taxonomy'] : $_REQUEST['taxonomy'];
208
+
209
+ if (!post_type_exists($post_type) || !taxonomy_exists($taxonomy))
210
+ return $out;
211
+
212
+ $term_id = (int) $term_id;
213
  $language = $this->model->get_language(substr($column, 9));
214
 
215
  if ($column == $this->get_first_language_column()) {
216
+ $out = sprintf('<div class="hidden" id="lang_%d">%s</div>', $term_id, esc_html($lang->slug));
217
 
218
  // identify the default categories to disable the language dropdown in js
219
  if (in_array(get_option('default_category'), $this->model->get_translations('term', $term_id)))
220
+ $out .= sprintf('<div class="hidden" id="default_cat_%1$d">%1$d</div>', $term_id);
221
  }
222
 
223
  // link to edit term (or a translation)
253
  $x = new WP_Ajax_Response();
254
  $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );
255
 
256
+ if (!post_type_exists($post_type = $_POST['post_type']))
257
+ die(0);
258
+
259
  $translations = empty($_POST['translations']) ? array() : explode(',', $_POST['translations']); // collect old translations
260
  $translations = array_merge($translations, array($_POST['post_id'])); // add current post
261
+ $translations = array_map('intval', $translations);
262
 
263
  foreach ($translations as $post_id) {
264
  $level = is_post_type_hierarchical( $post_type ) ? count( get_ancestors( $post_id, $post_type ) ) : 0;
286
  $x = new WP_Ajax_Response();
287
  $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) );
288
 
289
+ if (!taxonomy_exists($taxonomy = $_POST['taxonomy']))
290
+ die(0);
291
+
292
  $translations = empty($_POST['translations']) ? array() : explode(',', $_POST['translations']); // collect old translations
293
+ $translations = array_merge($translations, $this->model->get_translations('term', (int) $_POST['term_id'])); // add current translations
294
  $translations = array_unique($translations); // remove doublons
295
+ $translations = array_map('intval', $translations);
296
 
297
  foreach ($translations as $term_id) {
298
  $level = is_taxonomy_hierarchical($taxonomy) ? count( get_ancestors( $term_id, $taxonomy ) ) : 0;
admin/admin-filters-media.php CHANGED
@@ -100,12 +100,13 @@ class PLL_Admin_Filters_Media extends PLL_Admin_Filters_Post_Base {
100
  //security check
101
  check_admin_referer('translate_media');
102
 
103
- $post = get_post($_GET['from_media']);
104
  $post_id = $post->ID;
 
105
 
106
  // create a new attachment (translate attachment parent if exists)
107
  $post->ID = null; // will force the creation
108
- $post->post_parent = ($post->post_parent && $tr_parent = $this->model->get_translation('post', $post->post_parent, $_GET['new_lang'])) ? $tr_parent : 0;
109
  $tr_id = wp_insert_attachment($post);
110
  add_post_meta($tr_id, '_wp_attachment_metadata', get_post_meta($post_id, '_wp_attachment_metadata', true));
111
  add_post_meta($tr_id, '_wp_attached_file', get_post_meta($post_id, '_wp_attached_file', true));
@@ -118,7 +119,7 @@ class PLL_Admin_Filters_Media extends PLL_Admin_Filters_Post_Base {
118
  if (!$translations && $lang = $this->model->get_post_language($post_id))
119
  $translations[$lang->slug] = $post_id;
120
 
121
- $translations[$_GET['new_lang']] = $tr_id;
122
  $this->model->save_translations('post', $tr_id, $translations);
123
 
124
  do_action('pll_translate_media', $tr_id, $post, $translations);
100
  //security check
101
  check_admin_referer('translate_media');
102
 
103
+ $post = get_post((int) $_GET['from_media']);
104
  $post_id = $post->ID;
105
+ $new_lang = $this->model->get_language($_GET['new_lang']); // make sure we get a valid language slug
106
 
107
  // create a new attachment (translate attachment parent if exists)
108
  $post->ID = null; // will force the creation
109
+ $post->post_parent = ($post->post_parent && $tr_parent = $this->model->get_translation('post', $post->post_parent, $new_lang->slug)) ? $tr_parent : 0;
110
  $tr_id = wp_insert_attachment($post);
111
  add_post_meta($tr_id, '_wp_attachment_metadata', get_post_meta($post_id, '_wp_attachment_metadata', true));
112
  add_post_meta($tr_id, '_wp_attached_file', get_post_meta($post_id, '_wp_attached_file', true));
119
  if (!$translations && $lang = $this->model->get_post_language($post_id))
120
  $translations[$lang->slug] = $post_id;
121
 
122
+ $translations[$new_lang->slug] = $tr_id;
123
  $this->model->save_translations('post', $tr_id, $translations);
124
 
125
  do_action('pll_translate_media', $tr_id, $post, $translations);
admin/admin-filters-post-base.php CHANGED
@@ -30,8 +30,8 @@ abstract class PLL_Admin_Filters_Post_Base {
30
  */
31
  public function set_default_language($post_id) {
32
  if (!$this->model->get_post_language($post_id)) {
33
- if (isset($_GET['new_lang']))
34
- $this->model->set_post_language($post_id, $_GET['new_lang']);
35
 
36
  elseif (($parent_id = wp_get_post_parent_id($post_id)) && $parent_lang = $this->model->get_post_language($parent_id))
37
  $this->model->set_post_language($post_id, $parent_lang);
30
  */
31
  public function set_default_language($post_id) {
32
  if (!$this->model->get_post_language($post_id)) {
33
+ if (isset($_GET['new_lang']) && $lang = $this->model->get_language($_GET['new_lang']))
34
+ $this->model->set_post_language($post_id, $lang);
35
 
36
  elseif (($parent_id = wp_get_post_parent_id($post_id)) && $parent_lang = $this->model->get_post_language($parent_id))
37
  $this->model->set_post_language($post_id, $parent_lang);
admin/admin-filters-post.php CHANGED
@@ -92,7 +92,7 @@ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
92
 
93
  if (isset($qvars['post_type']) && !isset($qvars['lang'])) {
94
  // filters the list of media (or wp-links) by language when uploading from post
95
- if (isset($_REQUEST['pll_post_id']) && $lang = $this->model->get_post_language($_REQUEST['pll_post_id']))
96
  $query->set('lang', $lang->slug);
97
 
98
  elseif (!empty($this->curlang))
@@ -161,7 +161,7 @@ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
161
  check_ajax_referer('pll_language', '_pll_nonce');
162
 
163
  global $post_ID; // obliged to use the global variable for wp_popular_terms_checklist
164
- $post_ID = $_POST['post_id'];
165
  $post_type = get_post_type($post_ID);
166
  $lang = $this->model->get_language($_POST['lang']);
167
 
@@ -231,9 +231,15 @@ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
231
  public function ajax_posts_not_translated() {
232
  check_ajax_referer('pll_language', '_pll_nonce');
233
 
 
 
 
 
 
 
234
  // don't order by title: see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
235
  $args = array(
236
- 's' => $_REQUEST['term'],
237
  'suppress_filters' => 0, // to make the post_fields filter work
238
  'lang' => 0, // avoid admin language filter
239
  'numberposts' => 20, // limit to 20 posts
@@ -242,7 +248,7 @@ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
242
  'tax_query' => array(array(
243
  'taxonomy' => 'language',
244
  'field' => 'term_taxonomy_id', // WP 3.5+
245
- 'terms' => $this->model->get_language($_REQUEST['translation_language'])->term_taxonomy_id
246
  ))
247
  );
248
 
@@ -253,12 +259,12 @@ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
253
  $return = array();
254
 
255
  foreach ($posts as $key => $post) {
256
- if (!$this->model->get_translation('post', $post->ID, $_REQUEST['post_language']))
257
  $return[] = array('id' => $post->ID, 'value' => $post->post_title, 'link' => $this->edit_translation_link($post->ID));
258
  }
259
 
260
  // add current translation in list
261
- if ($post_id = $this->model->get_translation('post', $_REQUEST['pll_post_id'],$_REQUEST['translation_language'])) {
262
  $post = get_post($post_id);
263
  array_unshift($return, array(
264
  'id' => $post_id,
@@ -286,7 +292,7 @@ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
286
  // edit post
287
  if (isset($_REQUEST['post_lang_choice'])) {
288
  check_admin_referer('pll_language', '_pll_nonce');
289
- $this->model->set_post_language($post_id, $lang = $_REQUEST['post_lang_choice']);
290
  }
291
 
292
  // quick edit and bulk edit
@@ -301,14 +307,14 @@ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
301
  isset($_REQUEST['bulk_edit']) ? check_admin_referer('bulk-posts') : check_admin_referer('inlineeditnonce', '_inline_edit');
302
 
303
  $old_lang = $this->model->get_post_language($post_id); // stores the old language
304
- $this->model->set_post_language($post_id, $lang = $_REQUEST['inline_lang_choice']); // set new language
305
 
306
  // checks if the new language already exists in the translation group
307
- if ($old_lang && $old_lang->slug != $lang) {
308
  $translations = $this->model->get_translations('post', $post_id);
309
 
310
  // if yes, separate this post from the translation group
311
- if (array_key_exists($lang, $translations)) {
312
  $this->model->delete_translation('post', $post_id);
313
  }
314
 
92
 
93
  if (isset($qvars['post_type']) && !isset($qvars['lang'])) {
94
  // filters the list of media (or wp-links) by language when uploading from post
95
+ if (isset($_REQUEST['pll_post_id']) && $lang = $this->model->get_post_language((int) $_REQUEST['pll_post_id']))
96
  $query->set('lang', $lang->slug);
97
 
98
  elseif (!empty($this->curlang))
161
  check_ajax_referer('pll_language', '_pll_nonce');
162
 
163
  global $post_ID; // obliged to use the global variable for wp_popular_terms_checklist
164
+ $post_ID = (int) $_POST['post_id'];
165
  $post_type = get_post_type($post_ID);
166
  $lang = $this->model->get_language($_POST['lang']);
167
 
231
  public function ajax_posts_not_translated() {
232
  check_ajax_referer('pll_language', '_pll_nonce');
233
 
234
+ if (!post_type_exists($_REQUEST['post_type']))
235
+ die(0);
236
+
237
+ $post_language = $this->model->get_language($_REQUEST['post_language']);
238
+ $translation_language = $this->model->get_language($_REQUEST['translation_language']);
239
+
240
  // don't order by title: see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
241
  $args = array(
242
+ 's' => wp_unslash($_REQUEST['term']),
243
  'suppress_filters' => 0, // to make the post_fields filter work
244
  'lang' => 0, // avoid admin language filter
245
  'numberposts' => 20, // limit to 20 posts
248
  'tax_query' => array(array(
249
  'taxonomy' => 'language',
250
  'field' => 'term_taxonomy_id', // WP 3.5+
251
+ 'terms' => $translation_language->term_taxonomy_id
252
  ))
253
  );
254
 
259
  $return = array();
260
 
261
  foreach ($posts as $key => $post) {
262
+ if (!$this->model->get_translation('post', $post->ID, $post_language))
263
  $return[] = array('id' => $post->ID, 'value' => $post->post_title, 'link' => $this->edit_translation_link($post->ID));
264
  }
265
 
266
  // add current translation in list
267
+ if ($post_id = $this->model->get_translation('post', (int) $_REQUEST['pll_post_id'], $translation_language)) {
268
  $post = get_post($post_id);
269
  array_unshift($return, array(
270
  'id' => $post_id,
292
  // edit post
293
  if (isset($_REQUEST['post_lang_choice'])) {
294
  check_admin_referer('pll_language', '_pll_nonce');
295
+ $this->model->set_post_language($post_id, $lang = $this->model->get_language($_REQUEST['post_lang_choice']));
296
  }
297
 
298
  // quick edit and bulk edit
307
  isset($_REQUEST['bulk_edit']) ? check_admin_referer('bulk-posts') : check_admin_referer('inlineeditnonce', '_inline_edit');
308
 
309
  $old_lang = $this->model->get_post_language($post_id); // stores the old language
310
+ $this->model->set_post_language($post_id, $lang = $this->model->get_language($_REQUEST['inline_lang_choice'])); // set new language
311
 
312
  // checks if the new language already exists in the translation group
313
+ if ($old_lang && $old_lang->slug != $lang->slug) {
314
  $translations = $this->model->get_translations('post', $post_id);
315
 
316
  // if yes, separate this post from the translation group
317
+ if (array_key_exists($lang->slug, $translations)) {
318
  $this->model->delete_translation('post', $post_id);
319
  }
320
 
admin/admin-filters-term.php CHANGED
@@ -64,6 +64,10 @@ class PLL_Admin_Filters_Term {
64
  public function add_term_form() {
65
  $taxonomy = $_GET['taxonomy'];
66
  $post_type = isset($GLOBALS['post_type']) ? $GLOBALS['post_type'] : $_REQUEST['post_type'];
 
 
 
 
67
  $lang = isset($_GET['new_lang']) ? $this->model->get_language($_GET['new_lang']) : $this->pref_lang;
68
  $dropdown = new PLL_Walker_Dropdown();
69
 
@@ -105,6 +109,10 @@ class PLL_Admin_Filters_Term {
105
  $lang = $this->model->get_term_language($term_id);
106
  $taxonomy = $tag->taxonomy;
107
  $post_type = isset($GLOBALS['post_type']) ? $GLOBALS['post_type'] : $_REQUEST['post_type'];
 
 
 
 
108
  $dropdown = new PLL_Walker_Dropdown();
109
 
110
  // disable the language dropdown and the translations input fields for default categories to prevent removal
@@ -148,8 +156,9 @@ class PLL_Admin_Filters_Term {
148
  * @return string modified html
149
  */
150
  public function wp_dropdown_cats($output) {
151
- if (isset($_GET['taxonomy'], $_GET['from_tag'], $_GET['new_lang']) && $id = get_term($_GET['from_tag'], $_GET['taxonomy'])->parent) {
152
- if ($parent = $this->model->get_translation('term', $id, $_GET['new_lang']))
 
153
  return str_replace('"'.$parent.'"', '"'.$parent.'" selected="selected"', $output);
154
  }
155
  return $output;
@@ -207,7 +216,7 @@ class PLL_Admin_Filters_Term {
207
  else
208
  check_admin_referer('pll_language', '_pll_nonce'); // edit tags or tags metabox
209
 
210
- $this->model->set_term_language($term_id, $_POST['term_lang_choice']);
211
  }
212
 
213
  // *post* bulk edit, in case a new term is created
@@ -244,7 +253,7 @@ class PLL_Admin_Filters_Term {
244
  }
245
 
246
  else {
247
- $this->model->set_term_language($term_id, $_GET['inline_lang_choice']);
248
  }
249
  }
250
 
@@ -256,12 +265,12 @@ class PLL_Admin_Filters_Term {
256
  );
257
 
258
  $old_lang = $this->model->get_term_language($term_id); // stores the old language
259
- $lang = $_POST['inline_lang_choice']; // new language
260
  $translations = $this->model->get_translations('term', $term_id);
261
 
262
  // checks if the new language already exists in the translation group
263
- if ($old_lang && $old_lang->slug != $lang) {
264
- if (array_key_exists($lang, $translations)) {
265
  $this->model->delete_translation('term', $term_id);
266
  }
267
 
@@ -277,7 +286,7 @@ class PLL_Admin_Filters_Term {
277
  // edit post
278
  elseif (isset($_POST['post_lang_choice'])) {// FIXME should be useless now
279
  check_admin_referer('pll_language', '_pll_nonce');
280
- $this->model->set_term_language($term_id, $_POST['post_lang_choice']);
281
  }
282
 
283
  else
@@ -416,9 +425,12 @@ class PLL_Admin_Filters_Term {
416
  check_ajax_referer('pll_language', '_pll_nonce');
417
 
418
  $lang = $this->model->get_language($_POST['lang']);
419
- $term_id = isset($_POST['term_id']) ? $_POST['term_id'] : null;
420
  $taxonomy = $_POST['taxonomy'];
421
  $post_type = $_POST['post_type'];
 
 
 
422
 
423
  ob_start();
424
  if ($lang)
@@ -469,30 +481,40 @@ class PLL_Admin_Filters_Term {
469
  */
470
  public function ajax_terms_not_translated() {
471
  check_ajax_referer('pll_language', '_pll_nonce');
 
 
 
 
 
 
 
 
 
 
472
 
473
  $return = array();
474
 
475
  // it is more efficient to use one common query for all languages as soon as there are more than 2
476
  // pll_get_terms_not_translated arg to identify this query in terms_clauses filter
477
- foreach (get_terms($_REQUEST['taxonomy'], 'hide_empty=0&pll_get_terms_not_translated=1&name__like=' . $_REQUEST['term']) as $term) {
478
  $lang = $this->model->get_term_language($term->term_id);
479
 
480
- if ($lang && $lang->slug == $_REQUEST['translation_language'] && !$this->model->get_translation('term', $term->term_id, $_REQUEST['term_language']))
481
  $return[] = array(
482
  'id' => $term->term_id,
483
  'value' => $term->name,
484
- 'link' => $this->edit_translation_link($term->term_id, $_REQUEST['taxonomy'], $_REQUEST['post_type'])
485
  );
486
  }
487
 
488
  // add current translation in list
489
  // not in add term for as term_id is not set
490
- if ('undefined' !== $_REQUEST['term_id'] && $term_id = $this->model->get_translation('term', $_REQUEST['term_id'], $_REQUEST['translation_language'])) {
491
- $term = get_term($term_id, $_REQUEST['taxonomy']);
492
  array_unshift($return, array(
493
  'id' => $term_id,
494
  'value' => $term->name,
495
- 'link' => $this->edit_translation_link($term->term_id, $_REQUEST['taxonomy'], $_REQUEST['post_type'])
496
  ));
497
  }
498
 
@@ -522,10 +544,6 @@ class PLL_Admin_Filters_Term {
522
  if (isset($screen) && 'nav-menus' == $screen->base && in_array('nav_menu', $taxonomies))
523
  return $clauses;
524
 
525
- // don't filter category checklist in post list table as this will be handled by js
526
- if (isset($screen) && 'edit' == $screen->base)
527
- return $clauses;
528
-
529
  // if get_terms is queried with a 'lang' parameter
530
  if (!empty($args['lang']))
531
  return $this->model->terms_clauses($clauses, $args['lang']);
@@ -554,10 +572,6 @@ class PLL_Admin_Filters_Term {
554
  if (isset($_POST['lang']))
555
  $lang = $this->model->get_language($_POST['lang']);
556
 
557
- // ajax tag search since WP 3.7
558
- elseif (!empty($_GET['lang']) && isset($_GET['action']) && 'polylang-ajax-tag-search' == $_GET['action'])
559
- $lang = $this->model->get_language($_GET['lang']);
560
-
561
  // the post (or term) is created with the 'add new' (translation) link
562
  // test of $args['page'] to avoid filtering the terms list table in edit-tags panel
563
  elseif (!empty($_GET['new_lang']) && empty($args['page']))
@@ -582,7 +596,7 @@ class PLL_Admin_Filters_Term {
582
 
583
  // for the parent dropdown list in edit term
584
  elseif (isset($_GET['tag_ID']))
585
- $lang = $this->model->get_term_language($_GET['tag_ID']);
586
 
587
  // when a new category is created in the edit post panel
588
  elseif (isset($_POST['term_lang_choice']))
64
  public function add_term_form() {
65
  $taxonomy = $_GET['taxonomy'];
66
  $post_type = isset($GLOBALS['post_type']) ? $GLOBALS['post_type'] : $_REQUEST['post_type'];
67
+
68
+ if (!taxonomy_exists($taxonomy) || !post_type_exists($post_type))
69
+ return;
70
+
71
  $lang = isset($_GET['new_lang']) ? $this->model->get_language($_GET['new_lang']) : $this->pref_lang;
72
  $dropdown = new PLL_Walker_Dropdown();
73
 
109
  $lang = $this->model->get_term_language($term_id);
110
  $taxonomy = $tag->taxonomy;
111
  $post_type = isset($GLOBALS['post_type']) ? $GLOBALS['post_type'] : $_REQUEST['post_type'];
112
+
113
+ if (!post_type_exists($post_type))
114
+ return;
115
+
116
  $dropdown = new PLL_Walker_Dropdown();
117
 
118
  // disable the language dropdown and the translations input fields for default categories to prevent removal
156
  * @return string modified html
157
  */
158
  public function wp_dropdown_cats($output) {
159
+ if (isset($_GET['taxonomy'], $_GET['from_tag'], $_GET['new_lang']) && taxonomy_exists($_GET['taxonomy']) && $id = get_term((int) $_GET['from_tag'], $_GET['taxonomy'])->parent) {
160
+ $lang = $this->model->get_language($_GET['new_lang']);
161
+ if ($parent = $this->model->get_translation('term', $id, $lang))
162
  return str_replace('"'.$parent.'"', '"'.$parent.'" selected="selected"', $output);
163
  }
164
  return $output;
216
  else
217
  check_admin_referer('pll_language', '_pll_nonce'); // edit tags or tags metabox
218
 
219
+ $this->model->set_term_language($term_id, $this->model->get_language($_POST['term_lang_choice']));
220
  }
221
 
222
  // *post* bulk edit, in case a new term is created
253
  }
254
 
255
  else {
256
+ $this->model->set_term_language($term_id, $this->model->get_language($_GET['inline_lang_choice']));
257
  }
258
  }
259
 
265
  );
266
 
267
  $old_lang = $this->model->get_term_language($term_id); // stores the old language
268
+ $lang = $this->model->get_language($_POST['inline_lang_choice']); // new language
269
  $translations = $this->model->get_translations('term', $term_id);
270
 
271
  // checks if the new language already exists in the translation group
272
+ if ($old_lang && $old_lang->slug != $lang->slug) {
273
+ if (array_key_exists($lang->slug, $translations)) {
274
  $this->model->delete_translation('term', $term_id);
275
  }
276
 
286
  // edit post
287
  elseif (isset($_POST['post_lang_choice'])) {// FIXME should be useless now
288
  check_admin_referer('pll_language', '_pll_nonce');
289
+ $this->model->set_term_language($term_id, $this->model->get_language($_POST['post_lang_choice']));
290
  }
291
 
292
  else
425
  check_ajax_referer('pll_language', '_pll_nonce');
426
 
427
  $lang = $this->model->get_language($_POST['lang']);
428
+ $term_id = isset($_POST['term_id']) ? (int) $_POST['term_id'] : null;
429
  $taxonomy = $_POST['taxonomy'];
430
  $post_type = $_POST['post_type'];
431
+
432
+ if (!post_type_exists($post_type) || ! taxonomy_exists($taxonomy))
433
+ die(0);
434
 
435
  ob_start();
436
  if ($lang)
481
  */
482
  public function ajax_terms_not_translated() {
483
  check_ajax_referer('pll_language', '_pll_nonce');
484
+
485
+ $s = wp_unslash($_REQUEST['term']);
486
+ $post_type = $_REQUEST['post_type'];
487
+ $taxonomy = $_REQUEST['taxonomy'];
488
+
489
+ if (!post_type_exists($post_type) || ! taxonomy_exists($taxonomy))
490
+ die(0);
491
+
492
+ $term_language = $this->model->get_language($_REQUEST['term_language']);
493
+ $translation_language = $this->model->get_language($_REQUEST['translation_language']);
494
 
495
  $return = array();
496
 
497
  // it is more efficient to use one common query for all languages as soon as there are more than 2
498
  // pll_get_terms_not_translated arg to identify this query in terms_clauses filter
499
+ foreach (get_terms($taxonomy, 'hide_empty=0&pll_get_terms_not_translated=1&name__like=' . $s) as $term) {
500
  $lang = $this->model->get_term_language($term->term_id);
501
 
502
+ if ($lang && $lang->slug == $translation_language->slug && !$this->model->get_translation('term', $term->term_id, $term_language))
503
  $return[] = array(
504
  'id' => $term->term_id,
505
  'value' => $term->name,
506
+ 'link' => $this->edit_translation_link($term->term_id, $taxonomy, $post_type)
507
  );
508
  }
509
 
510
  // add current translation in list
511
  // not in add term for as term_id is not set
512
+ if ('undefined' !== $_REQUEST['term_id'] && $term_id = $this->model->get_translation('term', (int) $_REQUEST['term_id'], $translation_language)) {
513
+ $term = get_term($term_id, $taxonomy);
514
  array_unshift($return, array(
515
  'id' => $term_id,
516
  'value' => $term->name,
517
+ 'link' => $this->edit_translation_link($term->term_id, $taxonomy, $post_type)
518
  ));
519
  }
520
 
544
  if (isset($screen) && 'nav-menus' == $screen->base && in_array('nav_menu', $taxonomies))
545
  return $clauses;
546
 
 
 
 
 
547
  // if get_terms is queried with a 'lang' parameter
548
  if (!empty($args['lang']))
549
  return $this->model->terms_clauses($clauses, $args['lang']);
572
  if (isset($_POST['lang']))
573
  $lang = $this->model->get_language($_POST['lang']);
574
 
 
 
 
 
575
  // the post (or term) is created with the 'add new' (translation) link
576
  // test of $args['page'] to avoid filtering the terms list table in edit-tags panel
577
  elseif (!empty($_GET['new_lang']) && empty($args['page']))
596
 
597
  // for the parent dropdown list in edit term
598
  elseif (isset($_GET['tag_ID']))
599
+ $lang = $this->model->get_term_language((int) $_GET['tag_ID']);
600
 
601
  // when a new category is created in the edit post panel
602
  elseif (isset($_POST['term_lang_choice']))
admin/admin-filters.php CHANGED
@@ -77,8 +77,8 @@ class PLL_Admin_Filters extends PLL_Filters {
77
  * @return array widget options
78
  */
79
  public function widget_update_callback($instance, $new_instance, $old_instance, $widget) {
80
- if (!empty($_POST[$widget->id.'_lang_choice']))
81
- $instance['pll_lang'] = $_POST[$widget->id.'_lang_choice'];
82
  else
83
  unset($instance['pll_lang']);
84
 
@@ -95,7 +95,7 @@ class PLL_Admin_Filters extends PLL_Filters {
95
  public function personal_options_update($user_id) {
96
  // admin language
97
  $user_lang = in_array($_POST['user_lang'], $this->model->get_languages_list(array('fields' => 'locale'))) ? $_POST['user_lang'] : 0;
98
- update_user_meta($user_id, 'user_lang', $_POST['user_lang']);
99
 
100
  // biography translations
101
  foreach ($this->model->get_languages_list() as $lang) {
77
  * @return array widget options
78
  */
79
  public function widget_update_callback($instance, $new_instance, $old_instance, $widget) {
80
+ if (!empty($_POST[$key = $widget->id.'_lang_choice']) && in_array($_POST[$key], $this->model->get_languages_list(array('fields' => 'slug'))))
81
+ $instance['pll_lang'] = $_POST[$key];
82
  else
83
  unset($instance['pll_lang']);
84
 
95
  public function personal_options_update($user_id) {
96
  // admin language
97
  $user_lang = in_array($_POST['user_lang'], $this->model->get_languages_list(array('fields' => 'locale'))) ? $_POST['user_lang'] : 0;
98
+ update_user_meta($user_id, 'user_lang', $user_lang);
99
 
100
  // biography translations
101
  foreach ($this->model->get_languages_list() as $lang) {
admin/admin-model.php CHANGED
@@ -31,14 +31,14 @@ class PLL_Admin_Model extends PLL_Model {
31
  return false;
32
 
33
  // first the language taxonomy
34
- $description = serialize(array('locale' => $args['locale'], 'rtl' => $args['rtl']));
35
  $r = wp_insert_term($args['name'], 'language', array('slug' => $args['slug'], 'description' => $description));
36
  if (is_wp_error($r)) {
37
  // avoid an ugly fatal error if something went wrong (reported once in the forum)
38
  add_settings_error('general', 'pll_add_language', __('Impossible to add the language.', 'polylang'));
39
  return false;
40
  }
41
- wp_update_term((int) $r['term_id'], 'language', array('term_group' => $args['term_group'])); // can't set the term group directly in wp_insert_term
42
 
43
  // the term_language taxonomy
44
  // don't want shared terms so use a different slug
@@ -96,7 +96,6 @@ class PLL_Admin_Model extends PLL_Model {
96
  }
97
  }
98
 
99
-
100
  // delete menus locations
101
  if (!empty($this->options['nav_menus'])) {
102
  foreach ($this->options['nav_menus'] as $theme => $locations) {
@@ -171,7 +170,6 @@ class PLL_Admin_Model extends PLL_Model {
171
  $slug = $args['slug'];
172
  $old_slug = $lang->slug;
173
 
174
- // FIXME should do this in an action 'edit_term' to prevent translations to break when sharing a term with nav_menu?
175
  if ($old_slug != $slug) {
176
  // update the language slug in translations
177
  $this->update_translations($old_slug, $slug);
@@ -199,7 +197,6 @@ class PLL_Admin_Model extends PLL_Model {
199
  $this->options['nav_menus'][$theme][$location][$slug] = $this->options['nav_menus'][$theme][$location][$old_slug];
200
  unset($this->options['nav_menus'][$theme][$location][$old_slug]);
201
  }
202
-
203
  }
204
  }
205
  }
@@ -207,7 +204,7 @@ class PLL_Admin_Model extends PLL_Model {
207
  // update domains
208
  if (!empty($this->options['domains'][$old_slug])) {
209
  $this->options['domains'][$slug] = $this->options['domains'][$old_slug];
210
- unset($this->options['domains'][$slug]);
211
  }
212
 
213
  // update the default language option if necessary
@@ -218,8 +215,8 @@ class PLL_Admin_Model extends PLL_Model {
218
  update_option('polylang', $this->options);
219
 
220
  // and finally update the language itself
221
- $description = serialize(array('locale' => $args['locale'], 'rtl' => $args['rtl']));
222
- wp_update_term((int) $lang->term_id, 'language', array('slug' => $slug, 'name' => $args['name'], 'description' => $description, 'term_group' => $args['term_group']));
223
  wp_update_term((int) $lang->tl_term_id, 'term_language', array('slug' => 'pll_' . $slug, 'name' => $args['name']));
224
 
225
  $this->clean_languages_cache();
@@ -252,7 +249,8 @@ class PLL_Admin_Model extends PLL_Model {
252
  add_settings_error('general', 'pll_non_unique_slug', __('The language code must be unique', 'polylang'));
253
 
254
  // validate name
255
- if ($args['name'] == '')
 
256
  add_settings_error('general', 'pll_invalid_name', __('The language must have a name', 'polylang'));
257
 
258
  return get_settings_errors() ? false : true;
@@ -270,6 +268,7 @@ class PLL_Admin_Model extends PLL_Model {
270
  public function set_language_in_mass($type, $ids, $lang) {
271
  global $wpdb;
272
 
 
273
  $lang = $this->get_language($lang);
274
  $tt_id = 'term' == $type ? $lang->tl_term_taxonomy_id : $lang->term_taxonomy_id;
275
 
31
  return false;
32
 
33
  // first the language taxonomy
34
+ $description = serialize(array('locale' => $args['locale'], 'rtl' => (int) $args['rtl']));
35
  $r = wp_insert_term($args['name'], 'language', array('slug' => $args['slug'], 'description' => $description));
36
  if (is_wp_error($r)) {
37
  // avoid an ugly fatal error if something went wrong (reported once in the forum)
38
  add_settings_error('general', 'pll_add_language', __('Impossible to add the language.', 'polylang'));
39
  return false;
40
  }
41
+ wp_update_term((int) $r['term_id'], 'language', array('term_group' => (int) $args['term_group'])); // can't set the term group directly in wp_insert_term
42
 
43
  // the term_language taxonomy
44
  // don't want shared terms so use a different slug
96
  }
97
  }
98
 
 
99
  // delete menus locations
100
  if (!empty($this->options['nav_menus'])) {
101
  foreach ($this->options['nav_menus'] as $theme => $locations) {
170
  $slug = $args['slug'];
171
  $old_slug = $lang->slug;
172
 
 
173
  if ($old_slug != $slug) {
174
  // update the language slug in translations
175
  $this->update_translations($old_slug, $slug);
197
  $this->options['nav_menus'][$theme][$location][$slug] = $this->options['nav_menus'][$theme][$location][$old_slug];
198
  unset($this->options['nav_menus'][$theme][$location][$old_slug]);
199
  }
 
200
  }
201
  }
202
  }
204
  // update domains
205
  if (!empty($this->options['domains'][$old_slug])) {
206
  $this->options['domains'][$slug] = $this->options['domains'][$old_slug];
207
+ unset($this->options['domains'][$old_slug]);
208
  }
209
 
210
  // update the default language option if necessary
215
  update_option('polylang', $this->options);
216
 
217
  // and finally update the language itself
218
+ $description = serialize(array('locale' => $args['locale'], 'rtl' => (int) $args['rtl']));
219
+ wp_update_term((int) $lang->term_id, 'language', array('slug' => $slug, 'name' => $args['name'], 'description' => $description, 'term_group' => (int) $args['term_group']));
220
  wp_update_term((int) $lang->tl_term_id, 'term_language', array('slug' => 'pll_' . $slug, 'name' => $args['name']));
221
 
222
  $this->clean_languages_cache();
249
  add_settings_error('general', 'pll_non_unique_slug', __('The language code must be unique', 'polylang'));
250
 
251
  // validate name
252
+ // no need to sanitize it as wp_insert_term will do it for us
253
+ if (empty($args['name']))
254
  add_settings_error('general', 'pll_invalid_name', __('The language must have a name', 'polylang'));
255
 
256
  return get_settings_errors() ? false : true;
268
  public function set_language_in_mass($type, $ids, $lang) {
269
  global $wpdb;
270
 
271
+ $ids = array_map('intval', $ids);
272
  $lang = $this->get_language($lang);
273
  $tt_id = 'term' == $type ? $lang->tl_term_taxonomy_id : $lang->term_taxonomy_id;
274
 
admin/admin-nav-menu.php CHANGED
@@ -44,7 +44,8 @@ class PLL_Admin_Nav_Menu {
44
 
45
  // translation of menus based on chosen locations
46
  add_filter('pre_update_option_theme_mods_' . $this->theme, array($this, 'update_nav_menu_locations'));
47
- add_filter('theme_mod_nav_menu_locations', array($this, 'nav_menu_locations'), 20);
 
48
 
49
  // filter _wp_auto_add_pages_to_menu by language
50
  add_action('transition_post_status', array(&$this, 'auto_add_pages_to_menu'), 5, 3); // before _wp_auto_add_pages_to_menu
@@ -252,7 +253,7 @@ class PLL_Admin_Nav_Menu {
252
  if (is_array($menus)) {
253
  foreach ($menus as $loc => $menu) {
254
  foreach ($this->model->get_languages_list() as $lang) {
255
- if (pll_default_language() != $lang->slug && !empty($this->options['nav_menus'][$this->theme][$loc][$lang->slug]))
256
  $menus[$loc . '___' . $lang->slug] = $this->options['nav_menus'][$this->theme][$loc][$lang->slug];
257
  }
258
  }
@@ -261,6 +262,26 @@ class PLL_Admin_Nav_Menu {
261
  return $menus;
262
  }
263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  /*
265
  * filters _wp_auto_add_pages_to_menu by language
266
  *
44
 
45
  // translation of menus based on chosen locations
46
  add_filter('pre_update_option_theme_mods_' . $this->theme, array($this, 'update_nav_menu_locations'));
47
+ add_filter('theme_mod_nav_menu_locations', array($this, 'nav_menu_locations'), 20);
48
+ add_action('delete_nav_menu', array(&$this, 'delete_nav_menu'));
49
 
50
  // filter _wp_auto_add_pages_to_menu by language
51
  add_action('transition_post_status', array(&$this, 'auto_add_pages_to_menu'), 5, 3); // before _wp_auto_add_pages_to_menu
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]) && term_exists($this->options['nav_menus'][$this->theme][$loc][$lang->slug], 'nav_menu'))
257
  $menus[$loc . '___' . $lang->slug] = $this->options['nav_menus'][$this->theme][$loc][$lang->slug];
258
  }
259
  }
262
  return $menus;
263
  }
264
 
265
+ /*
266
+ * removes the nav menu term_id from the locations stored in Polylang options when a nav menu is deleted
267
+ *
268
+ * @since 1.7.3
269
+ *
270
+ * @param int nav menu id
271
+ */
272
+ function delete_nav_menu($term_id) {
273
+ foreach ($this->options['nav_menus'] as $theme => $locations) {
274
+ foreach ($locations as $loc => $languages) {
275
+ foreach ($languages as $lang => $menu_id) {
276
+ if ($menu_id === $term_id)
277
+ unset($this->options['nav_menus'][$theme][$loc][$lang]);
278
+ }
279
+ }
280
+ }
281
+
282
+ update_option('polylang', $this->options);
283
+ }
284
+
285
  /*
286
  * filters _wp_auto_add_pages_to_menu by language
287
  *
admin/admin-strings.php CHANGED
@@ -106,7 +106,7 @@ class PLL_Admin_Strings {
106
  * @return string
107
  */
108
  static public function sanitize_string_translation($translation, $name) {
109
- $translation = stripslashes(trim($translation));
110
 
111
  if (false !== ($option = array_search($name, self::$default_strings['options'], true)))
112
  $translation = sanitize_option($option, $translation);
@@ -115,7 +115,7 @@ class PLL_Admin_Strings {
115
  $translation = strip_tags($translation);
116
 
117
  if ($name == self::$default_strings['widget_text'] && !current_user_can('unfiltered_html'))
118
- $translation = stripslashes( wp_filter_post_kses( addslashes($translation) ) ); // wp_filter_post_kses() expects slashed
119
 
120
  return $translation;
121
  }
106
  * @return string
107
  */
108
  static public function sanitize_string_translation($translation, $name) {
109
+ $translation = wp_unslash(trim($translation));
110
 
111
  if (false !== ($option = array_search($name, self::$default_strings['options'], true)))
112
  $translation = sanitize_option($option, $translation);
115
  $translation = strip_tags($translation);
116
 
117
  if ($name == self::$default_strings['widget_text'] && !current_user_can('unfiltered_html'))
118
+ $translation = wp_unslash( wp_filter_post_kses( addslashes($translation) ) ); // wp_filter_post_kses() expects slashed
119
 
120
  return $translation;
121
  }
admin/admin-sync.php CHANGED
@@ -31,7 +31,7 @@ class PLL_Admin_Sync {
31
  * @since 0.6
32
  */
33
  function wp_insert_post_parent($post_parent) {
34
- return isset($_GET['from_post'], $_GET['new_lang']) && ($id = wp_get_post_parent_id($_GET['from_post'])) && ($parent = $this->model->get_translation('post', $id, $_GET['new_lang'])) ? $parent : $post_parent;
35
  }
36
 
37
  /*
@@ -47,15 +47,18 @@ class PLL_Admin_Sync {
47
  if ('post-new.php' == $GLOBALS['pagenow'] && isset($_GET['from_post'], $_GET['new_lang'])) {
48
  if (!$this->model->is_translated_post_type($post->post_type))
49
  return;
50
-
51
  // capability check already done in post-new.php
52
- $this->copy_post_metas($_GET['from_post'], $post->ID, $_GET['new_lang']);
 
 
 
53
 
54
- $from_post = get_post($_GET['from_post']);
55
  foreach (array('menu_order', 'comment_status', 'ping_status') as $property)
56
  $post->$property = $from_post->$property;
57
 
58
- if (in_array('sticky_posts', $this->options['sync']) && is_sticky($_GET['from_post']))
59
  stick_post($post->ID);
60
  }
61
  }
@@ -255,12 +258,12 @@ class PLL_Admin_Sync {
255
  continue;
256
 
257
  if (isset($_POST['parent']) && $_POST['parent'] != -1) // since WP 3.1
258
- $term_parent = $this->model->get_translation('term', $_POST['parent'], $lang);
259
 
260
  global $wpdb;
261
  $wpdb->update($wpdb->term_taxonomy,
262
  array('parent'=> isset($term_parent) ? $term_parent : 0),
263
- array('term_taxonomy_id' => get_term($tr_id, $taxonomy)->term_taxonomy_id));
264
  }
265
  }
266
  }
31
  * @since 0.6
32
  */
33
  function wp_insert_post_parent($post_parent) {
34
+ return isset($_GET['from_post'], $_GET['new_lang']) && ($id = wp_get_post_parent_id((int) $_GET['from_post'])) && ($parent = $this->model->get_translation('post', $id, $_GET['new_lang'])) ? $parent : $post_parent;
35
  }
36
 
37
  /*
47
  if ('post-new.php' == $GLOBALS['pagenow'] && isset($_GET['from_post'], $_GET['new_lang'])) {
48
  if (!$this->model->is_translated_post_type($post->post_type))
49
  return;
50
+
51
  // capability check already done in post-new.php
52
+ $from_post_id = (int) $_GET['from_post'];
53
+ $lang = $this->model->get_language($_GET['new_lang']);
54
+
55
+ $this->copy_post_metas($from_post_id, $post->ID, $lang->slug);
56
 
57
+ $from_post = get_post($from_post_id);
58
  foreach (array('menu_order', 'comment_status', 'ping_status') as $property)
59
  $post->$property = $from_post->$property;
60
 
61
+ if (in_array('sticky_posts', $this->options['sync']) && is_sticky($from_post_id))
62
  stick_post($post->ID);
63
  }
64
  }
258
  continue;
259
 
260
  if (isset($_POST['parent']) && $_POST['parent'] != -1) // since WP 3.1
261
+ $term_parent = $this->model->get_translation('term', (int) $_POST['parent'], $lang);
262
 
263
  global $wpdb;
264
  $wpdb->update($wpdb->term_taxonomy,
265
  array('parent'=> isset($term_parent) ? $term_parent : 0),
266
+ array('term_taxonomy_id' => get_term((int) $tr_id, $taxonomy)->term_taxonomy_id));
267
  }
268
  }
269
  }
admin/admin.php CHANGED
@@ -293,8 +293,6 @@ class PLL_Admin extends PLL_Base {
293
  if ($selected->slug == $lang->slug)
294
  continue;
295
 
296
- $img = empty($lang->flag) ? '' : (false !== strpos($lang->flag, 'img') ? $lang->flag . '&nbsp;' : $lang->flag);
297
-
298
  $wp_admin_bar->add_menu(array(
299
  'parent' => 'languages',
300
  'id' => $lang->slug,
293
  if ($selected->slug == $lang->slug)
294
  continue;
295
 
 
 
296
  $wp_admin_bar->add_menu(array(
297
  'parent' => 'languages',
298
  'id' => $lang->slug,
admin/settings.php CHANGED
@@ -115,17 +115,20 @@ class PLL_Settings {
115
  // get the strings to translate
116
  $data = PLL_Admin_Strings::get_strings();
117
 
118
- $selected = empty($_REQUEST['group']) ? -1 : $_REQUEST['group'];
119
- foreach ($data as $key=>$row) {
120
- $groups[] = $row['context']; // get the groups
121
 
122
- // filter for search string
123
- if (($selected !=-1 && $row['context'] != $selected) || (!empty($_REQUEST['s']) && stripos($row['name'], $_REQUEST['s']) === false && stripos($row['string'], $_REQUEST['s']) === false))
 
 
 
 
 
124
  unset ($data[$key]);
125
  }
126
 
127
- $groups = array_unique($groups);
128
-
129
  // load translations
130
  foreach ($listlanguages as $language) {
131
  // filters by language if requested
@@ -215,7 +218,7 @@ class PLL_Settings {
215
  $strings = PLL_Admin_Strings::get_strings();
216
 
217
  foreach ($this->model->get_languages_list() as $language) {
218
- if(empty($_POST['translation'][$language->slug])) // in case the language filter is active (thanks to John P. Bloch)
219
  continue;
220
 
221
  $mo = new PLL_MO();
115
  // get the strings to translate
116
  $data = PLL_Admin_Strings::get_strings();
117
 
118
+ // get the groups
119
+ foreach ($data as $key => $row)
120
+ $groups[] = $row['context'];
121
 
122
+ $groups = array_unique($groups);
123
+ $selected = empty($_REQUEST['group']) || !in_array($_REQUEST['group'], $groups) ? -1 : $_REQUEST['group'];
124
+ $s = empty($_REQUEST['s']) ? '' : wp_unslash($_REQUEST['s']);
125
+
126
+ // filter for search string
127
+ foreach ($data as $key => $row) {
128
+ if (($selected !=-1 && $row['context'] != $selected) || (!empty($s) && stripos($row['name'], $s) === false && stripos($row['string'], $s) === false))
129
  unset ($data[$key]);
130
  }
131
 
 
 
132
  // load translations
133
  foreach ($listlanguages as $language) {
134
  // filters by language if requested
218
  $strings = PLL_Admin_Strings::get_strings();
219
 
220
  foreach ($this->model->get_languages_list() as $language) {
221
+ if (empty($_POST['translation'][$language->slug])) // in case the language filter is active (thanks to John P. Bloch)
222
  continue;
223
 
224
  $mo = new PLL_MO();
admin/table-languages.php CHANGED
@@ -34,7 +34,18 @@ class PLL_Table_Languages extends WP_List_Table {
34
  * @return string
35
  */
36
  function column_default($item, $column_name) {
37
- return $item->$column_name;
 
 
 
 
 
 
 
 
 
 
 
38
  }
39
 
40
  /*
@@ -47,7 +58,7 @@ class PLL_Table_Languages extends WP_List_Table {
47
  * @return string
48
  */
49
  function column_name($item) {
50
- return $item->name . $this->row_actions(array(
51
  'edit' => sprintf(
52
  '<a href="%s">%s</a>',
53
  esc_url(admin_url('admin.php?page=mlang&amp;pll_action=edit&amp;lang=' . $item->term_id)),
@@ -89,11 +100,11 @@ class PLL_Table_Languages extends WP_List_Table {
89
  */
90
  function get_sortable_columns() {
91
  return array(
92
- 'name' => array('name', true), // sorted by name by default
93
- 'locale' => array('locale', false),
94
- 'slug' => array('slug', false),
95
  'term_group' => array('term_group', false),
96
- 'count' => array('count', false)
97
  );
98
  }
99
 
34
  * @return string
35
  */
36
  function column_default($item, $column_name) {
37
+ switch($column_name) {
38
+ case 'locale':
39
+ case 'slug':
40
+ return esc_html($item->$column_name);
41
+
42
+ case 'term_group':
43
+ case 'count':
44
+ return (int) $item->$column_name;
45
+
46
+ default:
47
+ return $item->$column_name; // flag
48
+ }
49
  }
50
 
51
  /*
58
  * @return string
59
  */
60
  function column_name($item) {
61
+ return esc_html($item->name) . $this->row_actions(array(
62
  'edit' => sprintf(
63
  '<a href="%s">%s</a>',
64
  esc_url(admin_url('admin.php?page=mlang&amp;pll_action=edit&amp;lang=' . $item->term_id)),
100
  */
101
  function get_sortable_columns() {
102
  return array(
103
+ 'name' => array('name', true), // sorted by name by default
104
+ 'locale' => array('locale', false),
105
+ 'slug' => array('slug', false),
106
  'term_group' => array('term_group', false),
107
+ 'count' => array('count', false)
108
  );
109
  }
110
 
frontend/choose-lang.php CHANGED
@@ -224,7 +224,7 @@ abstract class PLL_Choose_Lang {
224
  $query->set('page_id', $this->page_on_front);
225
  $query->is_singular = $query->is_page = true;
226
  $query->is_archive = $query->is_tax = false;
227
- unset($query->queried_object); // reset queried object
228
  }
229
 
230
  // takes care of paged front page
224
  $query->set('page_id', $this->page_on_front);
225
  $query->is_singular = $query->is_page = true;
226
  $query->is_archive = $query->is_tax = false;
227
+ unset($query->query_vars['lang'], $query->queried_object); // reset queried object
228
  }
229
 
230
  // takes care of paged front page
frontend/frontend-links.php CHANGED
@@ -238,7 +238,16 @@ class PLL_Frontend_Links extends PLL_Links {
238
  public function redirect_canonical($redirect_url, $requested_url) {
239
  global $wp_query;
240
  if (is_page() && !is_feed() && isset($wp_query->queried_object) && $wp_query->queried_object->ID == $this->page_on_front) {
241
- return is_paged() ? $this->links_model->add_paged_to_link($this->get_home_url(), $wp_query->query_vars['page']) : $this->get_home_url();
 
 
 
 
 
 
 
 
 
242
  }
243
 
244
  // protect against chained redirects
@@ -501,9 +510,13 @@ class PLL_Frontend_Links extends PLL_Links {
501
  $redirect_url = $requested_url;
502
  }
503
  else {
 
 
 
 
504
  $redirect_url = $this->options['force_lang'] ?
505
- $this->links_model->switch_language_in_link($requested_url, $language) :
506
- $this->links_model->remove_language_from_link($requested_url);
507
  }
508
 
509
  // allow plugins to change the redirection or even cancel it by setting $redirect_url to false
238
  public function redirect_canonical($redirect_url, $requested_url) {
239
  global $wp_query;
240
  if (is_page() && !is_feed() && isset($wp_query->queried_object) && $wp_query->queried_object->ID == $this->page_on_front) {
241
+ $url = is_paged() ? $this->links_model->add_paged_to_link($this->get_home_url(), $wp_query->query_vars['page']) : $this->get_home_url();
242
+
243
+ // don't forget additional query vars
244
+ $query = parse_url($redirect_url, PHP_URL_QUERY);
245
+ if (!empty($query)) {
246
+ parse_str($query, $query_vars);
247
+ $url = add_query_arg($query_vars, $url);
248
+ }
249
+
250
+ return $url;
251
  }
252
 
253
  // protect against chained redirects
510
  $redirect_url = $requested_url;
511
  }
512
  else {
513
+ // first get the canonical url evaluated by WP
514
+ $redirect_url = (!$redirect_url = redirect_canonical($requested_url, false)) ? $requested_url : $redirect_url;
515
+
516
+ // then get the right language code in url
517
  $redirect_url = $this->options['force_lang'] ?
518
+ $this->links_model->switch_language_in_link($redirect_url, $language) :
519
+ $this->links_model->remove_language_from_link($redirect_url); // works only for default permalinks
520
  }
521
 
522
  // allow plugins to change the redirection or even cancel it by setting $redirect_url to false
frontend/frontend-nav-menu.php CHANGED
@@ -124,7 +124,7 @@ class PLL_Frontend_Nav_Menu {
124
  */
125
  public function nav_menu_link_attributes($atts, $item, $args) {
126
  if (isset($item->lang))
127
- $atts['hreflang'] = $item->lang;
128
  return $atts;
129
  }
130
 
124
  */
125
  public function nav_menu_link_attributes($atts, $item, $args) {
126
  if (isset($item->lang))
127
+ $atts['hreflang'] = esc_attr($item->lang);
128
  return $atts;
129
  }
130
 
frontend/frontend.php CHANGED
@@ -114,15 +114,14 @@ class PLL_Frontend extends PLL_Base {
114
  // reset the queried object
115
  if (empty($taxonomies) && ($query->is_author || $query->is_post_type_archive || $query->is_date || $query->is_search)) {
116
  $query->is_tax = false;
117
- unset($query->queried_object);
118
- get_queried_object();
119
  }
120
 
121
  // move the language tax_query at the end to avoid it being the queried object
122
  if (!empty($taxonomies) && 'language' == reset( $queried_taxonomies )) {
123
  $query->tax_query->queried_terms['language'] = array_shift($query->tax_query->queried_terms);
124
  unset($query->queried_object);
125
- get_queried_object();
126
  }
127
  }
128
  }
114
  // reset the queried object
115
  if (empty($taxonomies) && ($query->is_author || $query->is_post_type_archive || $query->is_date || $query->is_search)) {
116
  $query->is_tax = false;
117
+ unset($query->queried_object); // FIXME useless?
 
118
  }
119
 
120
  // move the language tax_query at the end to avoid it being the queried object
121
  if (!empty($taxonomies) && 'language' == reset( $queried_taxonomies )) {
122
  $query->tax_query->queried_terms['language'] = array_shift($query->tax_query->queried_terms);
123
  unset($query->queried_object);
124
+ get_queried_object(); // necessary to avoid the language being the queried object
125
  }
126
  }
127
  }
include/language.php CHANGED
@@ -43,26 +43,36 @@ class PLL_Language {
43
  *
44
  * @since 1.2
45
  *
46
- * @param object $language 'language' term
47
  * @param object $term_language corresponding 'term_language' term
48
  */
49
- public function __construct($language, $term_language) {
50
- foreach ($language as $prop => $value)
51
- $this->$prop = in_array($prop, array('term_id', 'term_taxonomy_id', 'count')) ? (int) $language->$prop : $language->$prop;
 
 
 
 
 
 
 
 
52
 
53
- // although it would be convenient here, don't assume the term is shared between taxonomies as it may not be the case in future
54
- // http://make.wordpress.org/core/2013/07/28/potential-roadmap-for-taxonomy-meta-and-post-relationships/
55
- $this->tl_term_id = (int) $term_language->term_id;
56
- $this->tl_term_taxonomy_id = (int) $term_language->term_taxonomy_id;
57
- $this->tl_count = (int) $term_language->count;
58
 
59
- $description = maybe_unserialize($language->description);
60
- $this->locale = $description['locale'];
61
- $this->is_rtl = $description['rtl'];
62
 
63
- $this->description = &$this->locale; // backward compatibility with Polylang < 1.2
64
 
65
- $this->mo_id = PLL_MO::get_id($this);
 
 
66
  }
67
 
68
  /*
43
  *
44
  * @since 1.2
45
  *
46
+ * @param object|array $language 'language' term or language object properties stored as an array
47
  * @param object $term_language corresponding 'term_language' term
48
  */
49
+ public function __construct($language, $term_language = null) {
50
+ // build the object from all properties stored as an array
51
+ if (empty($term_language)) {
52
+ foreach ($language as $prop => $value)
53
+ $this->$prop = $value;
54
+ }
55
+
56
+ // build the object from taxonomies
57
+ else {
58
+ foreach ($language as $prop => $value)
59
+ $this->$prop = in_array($prop, array('term_id', 'term_taxonomy_id', 'count')) ? (int) $language->$prop : $language->$prop;
60
 
61
+ // although it would be convenient here, don't assume the term is shared between taxonomies as it may not be the case in future
62
+ // http://make.wordpress.org/core/2013/07/28/potential-roadmap-for-taxonomy-meta-and-post-relationships/
63
+ $this->tl_term_id = (int) $term_language->term_id;
64
+ $this->tl_term_taxonomy_id = (int) $term_language->term_taxonomy_id;
65
+ $this->tl_count = (int) $term_language->count;
66
 
67
+ $description = maybe_unserialize($language->description);
68
+ $this->locale = $description['locale'];
69
+ $this->is_rtl = $description['rtl'];
70
 
71
+ $this->description = &$this->locale; // backward compatibility with Polylang < 1.2
72
 
73
+ $this->mo_id = PLL_MO::get_id($this);
74
+ $this->set_flag();
75
+ }
76
  }
77
 
78
  /*
include/model.php CHANGED
@@ -61,7 +61,7 @@ class PLL_Model {
61
  public function _prime_terms_cache($terms, $taxonomies) {
62
  if ($this->is_translated_taxonomy($taxonomies)) {
63
  foreach ($terms as $term) {
64
- $term_ids[] = is_object($term) ? $term->term_id : $term;
65
  }
66
  }
67
 
@@ -101,6 +101,7 @@ class PLL_Model {
101
  if (empty($object_id))
102
  return false;
103
 
 
104
  $term = get_object_term_cache($object_id, $taxonomy);
105
 
106
  if (false === $term) {
@@ -146,6 +147,8 @@ class PLL_Model {
146
  */
147
  public function get_languages_list($args = array()) {
148
  if (false === $languages = $this->cache->get('languages')) {
 
 
149
  if ((defined('PLL_CACHE_LANGUAGES') && !PLL_CACHE_LANGUAGES) || false === ($languages = get_transient('pll_languages_list'))) {
150
  $languages = get_terms('language', array('hide_empty' => false, 'orderby'=> 'term_group'));
151
  $languages = empty($languages) || is_wp_error($languages) ? array() : $languages;
@@ -164,6 +167,13 @@ class PLL_Model {
164
  $languages = array(); // in case something went wrong
165
  }
166
  }
 
 
 
 
 
 
 
167
 
168
  $this->cache->set('languages', $languages);
169
 
@@ -188,21 +198,20 @@ class PLL_Model {
188
  * @since 1.4
189
  */
190
  public function _languages_list() {
191
- if ((defined('PLL_CACHE_LANGUAGES') && !PLL_CACHE_LANGUAGES) || false === get_transient('pll_languages_list')) {
192
- foreach ($languages = $this->cache->get('languages') as $language) {
193
- $language->set_flag();
194
-
195
- if (!defined('PLL_CACHE_HOME_URL') || PLL_CACHE_HOME_URL) {
196
- $language->set_home_url();
197
- }
198
- }
199
 
200
- if (!defined('PLL_CACHE_LANGUAGES') || PLL_CACHE_LANGUAGES)
201
- set_transient('pll_languages_list', $languages);
 
 
202
  }
203
 
204
  foreach ($this->cache->get('languages') as $language) {
205
- if (defined('PLL_CACHE_HOME_URL') && !PLL_CACHE_HOME_URL)
 
206
  $language->set_home_url();
207
 
208
  // ensures that the (possibly cached) home url uses the right scheme http or https
@@ -272,10 +281,14 @@ class PLL_Model {
272
  * @param array $translations: an associative array of translations with language code as key and translation id as value
273
  */
274
  public function save_translations($type, $id, $translations) {
275
- if (($lang = call_user_func(array(&$this, 'get_'.$type.'_language'), $id)) && isset($translations) && is_array($translations)) {
276
 
 
 
 
277
  $translations = array_merge(array($lang->slug => $id), $translations); // make sure this object is in translations
278
  $translations = array_diff($translations, array(0)); // don't keep non translated languages
 
279
 
280
  // unlink removed translations
281
  $old_translations = $this->get_translations($type, $id);
@@ -324,6 +337,7 @@ class PLL_Model {
324
  */
325
  public function delete_translation($type, $id) {
326
  global $wpdb;
 
327
  $term = $this->get_object_term($id, $type . '_translations');
328
 
329
  if (!empty($term)) {
@@ -364,7 +378,7 @@ class PLL_Model {
364
 
365
  $translations = $this->get_translations($type, $id);
366
 
367
- return isset($translations[$lang->slug]) ? (int) $translations[$lang->slug] : false;
368
  }
369
 
370
  /*
@@ -393,7 +407,7 @@ class PLL_Model {
393
  * @param int|string|object language (term_id or slug or object)
394
  */
395
  public function set_post_language($post_id, $lang) {
396
- wp_set_post_terms($post_id, $lang ? $this->get_language($lang)->slug : '', 'language' );
397
  }
398
 
399
  /*
@@ -419,7 +433,7 @@ class PLL_Model {
419
  * @return bool|int the translation post id if exists, otherwise the post id, false if the post has no language
420
  */
421
  public function get_post($post_id, $lang) {
422
- $post_lang = $this->get_post_language($post_id); // FIXME is this necessary?
423
  if (!$lang || !$post_lang)
424
  return false;
425
 
@@ -436,6 +450,7 @@ class PLL_Model {
436
  * @param int|string|object language (term_id or slug or object)
437
  */
438
  public function set_term_language($term_id, $lang) {
 
439
  wp_set_object_terms($term_id, $lang ? $this->get_language($lang)->tl_term_id : '', 'term_language');
440
 
441
  // add translation group for correct WXR export
@@ -765,6 +780,8 @@ class PLL_Model {
765
  public function term_exists($term_name, $taxonomy, $parent, $language) {
766
  global $wpdb;
767
 
 
 
768
  $select = "SELECT t.term_id FROM $wpdb->terms AS t";
769
  $join = " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id";
770
  $join .= $this->join_clause('term');
61
  public function _prime_terms_cache($terms, $taxonomies) {
62
  if ($this->is_translated_taxonomy($taxonomies)) {
63
  foreach ($terms as $term) {
64
+ $term_ids[] = is_object($term) ? $term->term_id : (int) $term;
65
  }
66
  }
67
 
101
  if (empty($object_id))
102
  return false;
103
 
104
+ $object_id = (int) $object_id;
105
  $term = get_object_term_cache($object_id, $taxonomy);
106
 
107
  if (false === $term) {
147
  */
148
  public function get_languages_list($args = array()) {
149
  if (false === $languages = $this->cache->get('languages')) {
150
+
151
+ // create the languages from taxonomies
152
  if ((defined('PLL_CACHE_LANGUAGES') && !PLL_CACHE_LANGUAGES) || false === ($languages = get_transient('pll_languages_list'))) {
153
  $languages = get_terms('language', array('hide_empty' => false, 'orderby'=> 'term_group'));
154
  $languages = empty($languages) || is_wp_error($languages) ? array() : $languages;
167
  $languages = array(); // in case something went wrong
168
  }
169
  }
170
+
171
+ // create the languages directly from arrays stored in transients
172
+ else {
173
+ foreach ($languages as $k => $v) {
174
+ $languages[$k] = new PLL_Language($v);
175
+ }
176
+ }
177
 
178
  $this->cache->set('languages', $languages);
179
 
198
  * @since 1.4
199
  */
200
  public function _languages_list() {
201
+ // cache the languages after getting the home urls
202
+ if ((!defined('PLL_CACHE_LANGUAGES') || PLL_CACHE_LANGUAGES) && false === get_transient('pll_languages_list')) {
203
+ foreach ($languages = $this->cache->get('languages') as $language)
204
+ $language->set_home_url();
 
 
 
 
205
 
206
+ // don't store directly objects as it badly break with some hosts (GoDaddy) due to race conditions when using object cache
207
+ // thanks to captin411 for catching this!
208
+ // see https://wordpress.org/support/topic/fatal-error-pll_model_languages_list?replies=8#post-6782255
209
+ set_transient('pll_languages_list', array_map(create_function('$o', 'return (array) $o;'), $languages));
210
  }
211
 
212
  foreach ($this->cache->get('languages') as $language) {
213
+ // get the home urls when not cached
214
+ if ((defined('PLL_CACHE_LANGUAGES') && !PLL_CACHE_LANGUAGES) || (defined('PLL_CACHE_HOME_URL') && !PLL_CACHE_HOME_URL))
215
  $language->set_home_url();
216
 
217
  // ensures that the (possibly cached) home url uses the right scheme http or https
281
  * @param array $translations: an associative array of translations with language code as key and translation id as value
282
  */
283
  public function save_translations($type, $id, $translations) {
284
+ $id = (int) $id;
285
 
286
+ if (($lang = call_user_func(array(&$this, 'get_'.$type.'_language'), $id)) && isset($translations) && is_array($translations)) {
287
+ // sanitize the translations array
288
+ $translations = array_map('intval', $translations);
289
  $translations = array_merge(array($lang->slug => $id), $translations); // make sure this object is in translations
290
  $translations = array_diff($translations, array(0)); // don't keep non translated languages
291
+ $translations = array_intersect_key($translations, array_flip($this->get_languages_list(array('fields' => 'slug')))); // keep only valid languages slugs as keys
292
 
293
  // unlink removed translations
294
  $old_translations = $this->get_translations($type, $id);
337
  */
338
  public function delete_translation($type, $id) {
339
  global $wpdb;
340
+ $id = (int) $id;
341
  $term = $this->get_object_term($id, $type . '_translations');
342
 
343
  if (!empty($term)) {
378
 
379
  $translations = $this->get_translations($type, $id);
380
 
381
+ return isset($translations[$lang->slug]) ? $translations[$lang->slug] : false;
382
  }
383
 
384
  /*
407
  * @param int|string|object language (term_id or slug or object)
408
  */
409
  public function set_post_language($post_id, $lang) {
410
+ wp_set_post_terms((int) $post_id, $lang ? $this->get_language($lang)->slug : '', 'language' );
411
  }
412
 
413
  /*
433
  * @return bool|int the translation post id if exists, otherwise the post id, false if the post has no language
434
  */
435
  public function get_post($post_id, $lang) {
436
+ $post_lang = $this->get_post_language($post_id);
437
  if (!$lang || !$post_lang)
438
  return false;
439
 
450
  * @param int|string|object language (term_id or slug or object)
451
  */
452
  public function set_term_language($term_id, $lang) {
453
+ $term_id = (int) $term_id;
454
  wp_set_object_terms($term_id, $lang ? $this->get_language($lang)->tl_term_id : '', 'term_language');
455
 
456
  // add translation group for correct WXR export
780
  public function term_exists($term_name, $taxonomy, $parent, $language) {
781
  global $wpdb;
782
 
783
+ $term_name = trim(wp_unslash($term_name));
784
+
785
  $select = "SELECT t.term_id FROM $wpdb->terms AS t";
786
  $join = " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id";
787
  $join .= $this->join_clause('term');
include/switcher.php CHANGED
@@ -48,7 +48,7 @@ class PLL_Switcher {
48
  foreach ($links->model->get_languages_list(array('hide_empty' => $args['hide_if_empty'])) as $language) {
49
  $id = (int) $language->term_id;
50
  $slug = $language->slug;
51
- $classes = array('lang-item', 'lang-item-' . esc_attr($id), 'lang-item-' . esc_attr($slug));
52
 
53
  if ($current_lang = pll_current_language() == $slug) {
54
  if ($args['hide_current'] && !$args['dropdown'])
48
  foreach ($links->model->get_languages_list(array('hide_empty' => $args['hide_if_empty'])) as $language) {
49
  $id = (int) $language->term_id;
50
  $slug = $language->slug;
51
+ $classes = array('lang-item', 'lang-item-' . $id, 'lang-item-' . esc_attr($slug));
52
 
53
  if ($current_lang = pll_current_language() == $slug) {
54
  if ($args['hide_current'] && !$args['dropdown'])
include/wpml-compat.php CHANGED
@@ -256,7 +256,7 @@ if (!function_exists('wpml_get_copied_fields_for_post_edit')) {
256
  return array();
257
 
258
  // don't know what WPML does but Polylang does copy all public meta keys by default
259
- foreach ($keys = array_unique(array_keys(get_post_custom($_GET['from_post']))) as $k => $meta_key)
260
  if (is_protected_meta($meta_key))
261
  unset ($keys[$k]);
262
 
256
  return array();
257
 
258
  // don't know what WPML does but Polylang does copy all public meta keys by default
259
+ foreach ($keys = array_unique(array_keys(get_post_custom((int) $_GET['from_post']))) as $k => $meta_key)
260
  if (is_protected_meta($meta_key))
261
  unset ($keys[$k]);
262
 
install/install-base.php CHANGED
@@ -24,7 +24,6 @@ class PLL_Install_Base {
24
  add_action('wpmu_new_blog', array(&$this, 'wpmu_new_blog'), 5); // before WP attempts to send mails which can break on some PHP versions
25
  }
26
 
27
-
28
  /*
29
  * allows to detect plugin deactivation
30
  *
@@ -43,9 +42,9 @@ class PLL_Install_Base {
43
  *
44
  * @param string $what either 'activate' or 'deactivate'
45
  */
46
- protected function do_for_all_blogs($what) {
47
  // network
48
- if (is_multisite() && isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
49
  global $wpdb;
50
 
51
  foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
@@ -65,8 +64,8 @@ class PLL_Install_Base {
65
  *
66
  * @since 1.7
67
  */
68
- public function activate() {
69
- $this->do_for_all_blogs('activate');
70
  }
71
 
72
  /*
@@ -83,8 +82,8 @@ class PLL_Install_Base {
83
  *
84
  * @since 0.1
85
  */
86
- public function deactivate() {
87
- $this->do_for_all_blogs('deactivate');
88
  }
89
 
90
  /*
24
  add_action('wpmu_new_blog', array(&$this, 'wpmu_new_blog'), 5); // before WP attempts to send mails which can break on some PHP versions
25
  }
26
 
 
27
  /*
28
  * allows to detect plugin deactivation
29
  *
42
  *
43
  * @param string $what either 'activate' or 'deactivate'
44
  */
45
+ protected function do_for_all_blogs($what, $networkwide) {
46
  // network
47
+ if (is_multisite() && $networkwide) {
48
  global $wpdb;
49
 
50
  foreach ($wpdb->get_col("SELECT blog_id FROM $wpdb->blogs") as $blog_id) {
64
  *
65
  * @since 1.7
66
  */
67
+ public function activate($networkwide) {
68
+ $this->do_for_all_blogs('activate', $networkwide);
69
  }
70
 
71
  /*
82
  *
83
  * @since 0.1
84
  */
85
+ public function deactivate($networkwide) {
86
+ $this->do_for_all_blogs('deactivate', $networkwide);
87
  }
88
 
89
  /*
install/install.php CHANGED
@@ -12,7 +12,7 @@ class PLL_Install extends PLL_Install_Base {
12
  *
13
  * @since 0.1
14
  */
15
- public function activate() {
16
  global $wp_version;
17
 
18
  Polylang::define_constants();
@@ -27,7 +27,7 @@ class PLL_Install extends PLL_Install_Base {
27
  )
28
  ));
29
 
30
- $this->do_for_all_blogs('activate');
31
  }
32
 
33
  /*
12
  *
13
  * @since 0.1
14
  */
15
+ public function activate($networkwide) {
16
  global $wp_version;
17
 
18
  Polylang::define_constants();
27
  )
28
  ));
29
 
30
+ $this->do_for_all_blogs('activate', $networkwide);
31
  }
32
 
33
  /*
polylang.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Polylang
4
  Plugin URI: http://polylang.wordpress.com/
5
- Version: 1.7.2
6
  Author: Frédéric Demarle
7
  Description: Adds multilingual capability to WordPress
8
  Text Domain: polylang
@@ -33,7 +33,7 @@ Domain Path: /languages
33
  if (!function_exists('add_action'))
34
  exit();
35
 
36
- define('POLYLANG_VERSION', '1.7.2');
37
  define('PLL_MIN_WP_VERSION', '3.8');
38
 
39
  define('POLYLANG_BASENAME', plugin_basename(__FILE__)); // plugin name as known by WP
2
  /*
3
  Plugin Name: Polylang
4
  Plugin URI: http://polylang.wordpress.com/
5
+ Version: 1.7.3
6
  Author: Frédéric Demarle
7
  Description: Adds multilingual capability to WordPress
8
  Text Domain: polylang
33
  if (!function_exists('add_action'))
34
  exit();
35
 
36
+ define('POLYLANG_VERSION', '1.7.3');
37
  define('PLL_MIN_WP_VERSION', '3.8');
38
 
39
  define('POLYLANG_BASENAME', plugin_basename(__FILE__)); // plugin name as known by WP
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: Chouby
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CCWWYUUQV8F4E
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, international, localization
5
  Requires at least: 3.8
6
- Tested up to: 4.1
7
- Stable tag: 1.7.2
8
  License: GPLv2 or later
9
 
10
  Polylang adds multilingual content management support to WordPress.
@@ -67,6 +67,17 @@ See http://polylang.wordpress.com/documentation/contribute/
67
 
68
  == Changelog ==
69
 
 
 
 
 
 
 
 
 
 
 
 
70
  = 1.7.2 (2015-03-23) =
71
 
72
  * fix: comments are filtered for posts in a post type not managed by Polylang
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CCWWYUUQV8F4E
4
  Tags: multilingual, bilingual, translate, translation, language, multilanguage, international, localization
5
  Requires at least: 3.8
6
+ Tested up to: 4.2
7
+ Stable tag: 1.7.3
8
  License: GPLv2 or later
9
 
10
  Polylang adds multilingual content management support to WordPress.
67
 
68
  == Changelog ==
69
 
70
+ = 1.7.3 (2015-04-11) =
71
+
72
+ * the transient 'pll_languages_list' now stores an array of arrays instead of an array of PLL_Language objects
73
+ * fix: fatal error for users hosted at GoDaddy (due to PLL_Language objects stored in a transient)
74
+ * fix: additional query vars are removed from home page
75
+ * fix: categories are not filtered by the admin language switcher in posts list table (introduced in 1.7)
76
+ * fix: when using multiple domains, the domain url is lost when modifying the language slug
77
+ * fix: the queried object is incorrectly set for author archives (introduced in 1.6.5)
78
+ * fix: notice when a nav menu assigned to a translated nav menu location has been deleted
79
+ * fix: no canonical redirection when using pretty permalinks and querying default permalinks
80
+
81
  = 1.7.2 (2015-03-23) =
82
 
83
  * fix: comments are filtered for posts in a post type not managed by Polylang