PluginProbe
Polylang / 2.0.12
Polylang v2.0.12
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
← All changes | admin/admin-filters-post.php +451 -91 2.8.3 → 2.0.12 View file →
@@ -1,19 +1,16 @@
1 1 <?php
2 -/**
3 - * @package Polylang
4 - */
5 2
6 3 /**
7 - * Manages filters and actions related to posts on admin side
4 + * manages filters and actions related to posts on admin side
8 5 *
9 6 * @since 1.2
10 7 */
11 8 class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
12 - public $curlang;
9 + public $options, $curlang;
13 10
14 11 /**
15 - * Constructor: setups filters and actions
12 + * constructor: setups filters and actions
16 13 *
17 14 * @since 1.2
18 15 *
19 16 * @param object $polylang
@@ -19,28 +16,39 @@
19 16 * @param object $polylang
20 17 */
21 18 public function __construct( &$polylang ) {
22 19 parent::__construct( $polylang );
20 + $this->options = &$polylang->options;
23 21 $this->curlang = &$polylang->curlang;
24 22
25 23 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
26 24
27 - // Filters posts, pages and media by language
25 + // filters posts, pages and media by language
28 26 add_action( 'parse_query', array( $this, 'parse_query' ) );
29 27
30 - // Adds actions and filters related to languages when creating, saving or deleting posts and pages
31 - add_action( 'load-post.php', array( $this, 'edit_post' ) );
32 - add_action( 'load-edit.php', array( $this, 'bulk_edit_posts' ) );
33 - add_action( 'wp_ajax_inline-save', array( $this, 'inline_edit_post' ), 0 ); // Before WordPress
28 + // adds the Languages box in the 'Edit Post' and 'Edit Page' panels
29 + add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 10, 2 );
34 30
35 - // Sets the language in Tiny MCE
36 - add_filter( 'tiny_mce_before_init', array( $this, 'tiny_mce_before_init' ) );
31 + // ajax response for changing the language in the post metabox
32 + add_action( 'wp_ajax_post_lang_choice', array( $this, 'post_lang_choice' ) );
33 + add_action( 'wp_ajax_pll_posts_not_translated', array( $this, 'ajax_posts_not_translated' ) );
34 +
35 + // adds actions and filters related to languages when creating, saving or deleting posts and pages
36 + add_action( 'save_post', array( $this, 'save_post' ), 21, 3 ); // priority 21 to come after advanced custom fields ( 20 ) and before the event calendar which breaks everything after 25
37 + add_filter( 'wp_insert_post_parent', array( $this, 'wp_insert_post_parent' ), 10, 4 );
38 + add_action( 'before_delete_post', array( $this, 'delete_post' ) );
39 + if ( $this->options['media_support'] ) {
40 + add_action( 'delete_attachment', array( $this, 'delete_post' ) ); // action shared with media
41 + }
42 +
43 + // filters the pages by language in the parent dropdown list in the page attributes metabox
44 + add_filter( 'page_attributes_dropdown_pages_args', array( $this, 'page_attributes_dropdown_pages_args' ), 10, 2 );
37 45 }
38 46
39 47 /**
40 - * Outputs a javascript list of terms ordered by language and hierarchical taxonomies
48 + * outputs a javascript list of terms ordered by language and hierarchical taxonomies
41 49 * to filter the category checklist per post language in quick edit
42 - * Outputs a javascript list of pages ordered by language
50 + * outputs a javascript list of pages ordered by language
43 51 * to filter the parent dropdown per post language in quick edit
44 52 *
45 53 * @since 1.7
46 54 */
@@ -46,12 +54,11 @@
46 54 */
47 55 public function admin_enqueue_scripts() {
48 56 $screen = get_current_screen();
49 57
50 - // Hierarchical taxonomies
58 + //hierarchical taxonomies
51 59 if ( 'edit' == $screen->base && $taxonomies = get_object_taxonomies( $screen->post_type, 'object' ) ) {
52 - // Get translated hierarchical taxonomies
53 - $hierarchical_taxonomies = array();
60 + // get translated hierarchical taxonomies
54 61 foreach ( $taxonomies as $taxonomy ) {
55 62 if ( $taxonomy->hierarchical && $taxonomy->show_in_quick_edit && $this->model->is_translated_taxonomy( $taxonomy->name ) ) {
56 63 $hierarchical_taxonomies[] = $taxonomy->name;
57 64 }
@@ -57,10 +64,9 @@
57 64 }
58 65 }
59 66
60 67 if ( ! empty( $hierarchical_taxonomies ) ) {
61 - $terms = get_terms( $hierarchical_taxonomies, array( 'get' => 'all' ) );
62 - $term_languages = array();
68 + $terms = get_terms( $hierarchical_taxonomies, array( 'get' => 'all' ) );
63 69
64 70 foreach ( $terms as $term ) {
65 71 if ( $lang = $this->model->term->get_language( $term->term_id ) ) {
66 72 $term_languages[ $lang->slug ][ $term->taxonomy ][] = $term->term_id;
@@ -66,9 +72,9 @@
66 72 $term_languages[ $lang->slug ][ $term->taxonomy ][] = $term->term_id;
67 73 }
68 74 }
69 75
70 - // Send all these data to javascript
76 + // send all these data to javascript
71 77 if ( ! empty( $term_languages ) ) {
72 78 wp_localize_script( 'pll_post', 'pll_term_languages', $term_languages );
73 79 }
74 80 }
@@ -73,15 +79,12 @@
73 79 }
74 80 }
75 81 }
76 82
77 - // Hierarchical post types
83 + // hierarchical post types
78 84 if ( 'edit' == $screen->base && is_post_type_hierarchical( $screen->post_type ) ) {
79 - $pages = get_pages( array( 'sort_column' => 'menu_order, post_title' ) ); // Same arguments as the parent pages dropdown to avoid an extra query.
80 - update_post_caches( $pages, $screen->post_type );
85 + $pages = get_pages();
81 86
82 - $page_languages = array();
83 -
84 87 foreach ( $pages as $page ) {
85 88 if ( $lang = $this->model->post->get_language( $page->ID ) ) {
86 89 $page_languages[ $lang->slug ][] = $page->ID;
87 90 }
@@ -86,9 +89,9 @@
86 89 $page_languages[ $lang->slug ][] = $page->ID;
87 90 }
88 91 }
89 92
90 - // Send all these data to javascript
93 + // send all these data to javascript
91 94 if ( ! empty( $page_languages ) ) {
92 95 wp_localize_script( 'pll_post', 'pll_page_languages', $page_languages );
93 96 }
94 97 }
@@ -94,9 +97,9 @@
94 97 }
95 98 }
96 99
97 100 /**
98 - * Filters posts, pages and media by language
101 + * filters posts, pages and media by language
99 102 *
100 103 * @since 0.1
101 104 *
102 105 * @param object $query a WP_Query object
@@ -101,63 +104,367 @@
101 104 *
102 105 * @param object $query a WP_Query object
103 106 */
104 107 public function parse_query( $query ) {
105 - $pll_query = new PLL_Query( $query, $this->model );
106 - $pll_query->filter_query( $this->curlang );
108 + $qvars = &$query->query_vars;
109 +
110 + // do not filter post types such as nav_menu_item
111 + if ( isset( $qvars['post_type'] ) && ! $this->model->is_translated_post_type( $qvars['post_type'] ) ) {
112 + unset( $qvars['lang'] );
113 + return;
114 + }
115 +
116 + // Do not filter the query if the language is already specified in another way
117 + if ( ! isset( $qvars['lang'] ) ) {
118 + $excludes = array(
119 + 'p', 'post_parent', 'attachment', 'attachment_id', 'name', 'pagename', 'page_id',
120 + 'category_name', 'tag', 'cat', 'tag_id', 'category__in', 'category__not_in', 'category__and',
121 + 'post__in', 'post__not_in', 'post_name__in', 'tag__in', 'tag__not_in', 'tag__and',
122 + 'tag_slug__in', 'tag_slug__and', 'post_parent__in', 'post_parent__not_in',
123 + );
124 +
125 + foreach ( $excludes as $k ) {
126 + if ( ! empty( $qvars[ $k ] ) ) {
127 + return;
128 + }
129 + }
130 +
131 + $taxonomies = array_intersect( $this->model->get_translated_taxonomies(), get_taxonomies( array( '_builtin' => false ) ) );
132 +
133 + foreach ( $taxonomies as $tax ) {
134 + $tax = get_taxonomy( $tax );
135 + if ( ! empty( $qv[ $tax->query_var ] ) ) {
136 + return;
137 + }
138 + }
139 +
140 + if ( ! empty( $qvars['tax_query'] ) && is_array( $qvars['tax_query'] ) && $this->model->have_translated_taxonomy( $qvars['tax_query'] ) ) {
141 + return;
142 + }
143 +
144 + // Filter queries according to the current language
145 + if ( isset( $qvars['post_type'] ) && ! empty( $this->curlang ) ) {
146 + $qvars['lang'] = $this->curlang->slug;
147 + }
148 + }
149 +
150 +
151 + if ( isset( $qvars['lang'] ) && 'all' === $qvars['lang'] ) {
152 + unset( $qvars['lang'] );
153 + }
107 154 }
108 155
109 156 /**
110 - * Save language and translation when editing a post (post.php)
157 + * Adds the Language box in the 'Edit Post' and 'Edit Page' panels ( as well as in custom post types panels )
158 + * Removes the editor for translations of the pages for posts
111 159 *
112 - * @since 2.3
160 + * @since 0.1
161 + *
162 + * @param string $post_type
113 163 */
114 - public function edit_post() {
115 - if ( isset( $_POST['post_lang_choice'], $_POST['post_ID'] ) && $post_id = (int) $_POST['post_ID'] ) { // phpcs:ignore WordPress.Security.NonceVerification
116 - check_admin_referer( 'pll_language', '_pll_nonce' );
164 + public function add_meta_boxes( $post_type, $post ) {
165 + if ( $this->model->is_translated_post_type( $post_type ) ) {
166 + add_meta_box( 'ml_box', __( 'Languages','polylang' ), array( $this, 'post_language' ), $post_type, 'side', 'high' );
167 + }
117 168
118 - $post = get_post( $post_id );
119 - $post_type_object = get_post_type_object( $post->post_type );
169 + if ( ( $page_for_posts = get_option( 'page_for_posts' ) ) && ( $translations = $this->model->post->get_translations( $page_for_posts ) ) && in_array( $post->ID, $translations ) && empty( $post->post_content ) ) {
170 + add_action( 'edit_form_after_title', '_wp_posts_page_notice' );
171 + remove_post_type_support( $post_type, 'editor' );
172 + }
173 + }
120 174
121 - if ( current_user_can( $post_type_object->cap->edit_post, $post_id ) ) {
122 - $this->model->post->set_language( $post_id, $this->model->get_language( sanitize_key( $_POST['post_lang_choice'] ) ) );
175 + /**
176 + * displays the Languages metabox in the 'Edit Post' and 'Edit Page' panels
177 + *
178 + * @since 0.1
179 + */
180 + public function post_language() {
181 + global $post_ID;
182 + $post_id = $post_ID;
183 + $post_type = get_post_type( $post_ID );
123 184
124 - if ( isset( $_POST['post_tr_lang'] ) ) {
125 - $this->save_translations( $post_id, array_map( 'absint', $_POST['post_tr_lang'] ) );
126 - }
185 + $lang = ( $lg = $this->model->post->get_language( $post_ID ) ) ? $lg :
186 + ( isset( $_GET['new_lang'] ) ? $this->model->get_language( $_GET['new_lang'] ) :
187 + $this->pref_lang );
188 +
189 + $dropdown = new PLL_Walker_Dropdown();
190 +
191 + wp_nonce_field( 'pll_language', '_pll_nonce' );
192 +
193 + // NOTE: the class "tags-input" allows to include the field in the autosave $_POST ( see autosave.js )
194 + printf( '
195 + <p><strong>%1$s</strong></p>
196 + <label class="screen-reader-text" for="%2$s">%1$s</label>
197 + <div id="select-%3$s-language">%4$s</div>',
198 + esc_html__( 'Language', 'polylang' ),
199 + $id = ( 'attachment' === $post_type ) ? sprintf( 'attachments[%d][language]', $post_ID ) : 'post_lang_choice',
200 + 'attachment' === $post_type ? 'media' : 'post',
201 + $dropdown->walk( $this->model->get_languages_list(), array(
202 + 'name' => $id,
203 + 'class' => 'post_lang_choice tags-input',
204 + 'selected' => $lang ? $lang->slug : '',
205 + 'flag' => true,
206 + ) )
207 + );
208 +
209 + /**
210 + * Fires before displaying the list of translations in the Languages metabox for posts
211 + *
212 + * @since 1.8
213 + */
214 + do_action( 'pll_before_post_translations', $post_type );
215 +
216 + echo '<div id="post-translations" class="translations">';
217 + if ( $lang ) {
218 + include( PLL_ADMIN_INC . '/view-translations-' . ( 'attachment' == $post_type ? 'media' : 'post' ) . '.php' );
219 + }
220 + echo '</div>' . "\n";
221 + }
222 +
223 + /**
224 + * ajax response for changing the language in the post metabox
225 + *
226 + * @since 0.2
227 + */
228 + public function post_lang_choice() {
229 + check_ajax_referer( 'pll_language', '_pll_nonce' );
230 +
231 + global $post_ID; // obliged to use the global variable for wp_popular_terms_checklist
232 + $post_id = $post_ID = (int) $_POST['post_id'];
233 + $lang = $this->model->get_language( $_POST['lang'] );
234 +
235 + $post_type = $_POST['post_type'];
236 + $post_type_object = get_post_type_object( $post_type );
237 + if ( ! current_user_can( $post_type_object->cap->edit_post, $post_ID ) ) {
238 + wp_die( -1 );
239 + }
240 +
241 + $this->model->post->set_language( $post_ID, $lang ); // save language, useful to set the language when uploading media from post
242 +
243 + ob_start();
244 + if ( $lang ) {
245 + include( PLL_ADMIN_INC . '/view-translations-' . ( 'attachment' == $post_type ? 'media' : 'post' ) . '.php' );
246 + }
247 + $x = new WP_Ajax_Response( array( 'what' => 'translations', 'data' => ob_get_contents() ) );
248 + ob_end_clean();
249 +
250 + // categories
251 + if ( isset( $_POST['taxonomies'] ) ) {
252 + // not set for pages
253 + foreach ( $_POST['taxonomies'] as $taxname ) {
254 + $taxonomy = get_taxonomy( $taxname );
255 +
256 + ob_start();
257 + $popular_ids = wp_popular_terms_checklist( $taxonomy->name );
258 + $supplemental['populars'] = ob_get_contents();
259 + ob_end_clean();
260 +
261 + ob_start();
262 + // use $post_ID to remember ckecked terms in case we come back to the original language
263 + wp_terms_checklist( $post_ID, array( 'taxonomy' => $taxonomy->name, 'popular_cats' => $popular_ids ) );
264 + $supplemental['all'] = ob_get_contents();
265 + ob_end_clean();
266 +
267 + $supplemental['dropdown'] = wp_dropdown_categories( array(
268 + 'taxonomy' => $taxonomy->name,
269 + 'hide_empty' => 0,
270 + 'name' => 'new'.$taxonomy->name.'_parent',
271 + 'orderby' => 'name',
272 + 'hierarchical' => 1,
273 + 'show_option_none' => '&mdash; '.$taxonomy->labels->parent_item.' &mdash;',
274 + 'echo' => 0,
275 + ) );
276 +
277 + $x->Add( array( 'what' => 'taxonomy', 'data' => $taxonomy->name, 'supplemental' => $supplemental ) );
127 278 }
128 279 }
280 +
281 + // parent dropdown list ( only for hierarchical post types )
282 + if ( in_array( $post_type, get_post_types( array( 'hierarchical' => true ) ) ) ) {
283 + $post = get_post( $post_ID );
284 +
285 + // args and filter from 'page_attributes_meta_box' in wp-admin/includes/meta-boxes.php of WP 4.2.1
286 + $dropdown_args = array(
287 + 'post_type' => $post->post_type,
288 + 'exclude_tree' => $post->ID,
289 + 'selected' => $post->post_parent,
290 + 'name' => 'parent_id',
291 + 'show_option_none' => __( '(no parent)' ),
292 + 'sort_column' => 'menu_order, post_title',
293 + 'echo' => 0,
294 + );
295 +
296 + /** This filter is documented in wp-admin/includes/meta-boxes.php */
297 + $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post ); // since WP 3.3
298 +
299 + $x->Add( array( 'what' => 'pages', 'data' => wp_dropdown_pages( $dropdown_args ) ) );
300 + }
301 +
302 + // flag
303 + $x->Add( array( 'what' => 'flag', 'data' => empty( $lang->flag ) ? esc_html( $lang->slug ) : $lang->flag ) );
304 +
305 + // Sample permalink
306 + $x->Add( array( 'what' => 'permalink', 'data' => get_sample_permalink_html( $post_ID ) ) );
307 +
308 + $x->send();
129 309 }
130 310
131 311 /**
132 - * Save language when inline editing or bulk editing a post
133 - * Fix translations if necessary
312 + * ajax response for input in translation autocomplete input box
134 313 *
135 - * @since 2.3
314 + * @since 1.5
315 + */
316 + public function ajax_posts_not_translated() {
317 + check_ajax_referer( 'pll_language', '_pll_nonce' );
318 +
319 + if ( ! post_type_exists( $_GET['post_type'] ) ) {
320 + die( 0 );
321 + }
322 +
323 + $post_language = $this->model->get_language( $_GET['post_language'] );
324 + $translation_language = $this->model->get_language( $_GET['translation_language'] );
325 +
326 + // don't order by title: see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
327 + $args = array(
328 + 's' => wp_unslash( $_GET['term'] ),
329 + 'suppress_filters' => 0, // to make the post_fields filter work
330 + 'lang' => 0, // avoid admin language filter
331 + 'numberposts' => 20, // limit to 20 posts
332 + 'post_status' => 'any',
333 + 'post_type' => $_GET['post_type'],
334 + 'tax_query' => array( array(
335 + 'taxonomy' => 'language',
336 + 'field' => 'term_taxonomy_id', // WP 3.5+
337 + 'terms' => $translation_language->term_taxonomy_id,
338 + ) ),
339 + );
340 +
341 + /**
342 + * Filter the query args when auto suggesting untranslated posts in the Languages metabox
343 + * This should help plugins to fix some edge cases
344 + *
345 + * @see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
346 + *
347 + * @since 1.7
348 + *
349 + * @param array $args WP_Query arguments
350 + */
351 + $args = apply_filters( 'pll_ajax_posts_not_translated_args', $args );
352 + $posts = get_posts( $args );
353 +
354 + $return = array();
355 +
356 + foreach ( $posts as $key => $post ) {
357 + if ( ! $this->model->post->get_translation( $post->ID, $post_language ) ) {
358 + $return[] = array(
359 + 'id' => $post->ID,
360 + 'value' => $post->post_title,
361 + 'link' => $this->links->edit_post_translation_link( $post->ID ),
362 + );
363 + }
364 + }
365 +
366 + // add current translation in list
367 + if ( $post_id = $this->model->post->get_translation( (int) $_GET['pll_post_id'], $translation_language ) ) {
368 + $post = get_post( $post_id );
369 + array_unshift( $return, array(
370 + 'id' => $post_id,
371 + 'value' => $post->post_title,
372 + 'link' => $this->links->edit_post_translation_link( $post_id ),
373 + ) );
374 + }
375 +
376 + wp_die( json_encode( $return ) );
377 + }
378 +
379 + /**
380 + * saves language
381 + * checks the terms saved are in the right language
136 382 *
137 - * @param int $post_id Post ID
138 - * @param object $lang Language
383 + * @since 1.5
384 + *
385 + * @param int $post_id
386 + * @param array $post
139 387 */
140 - protected function inline_save_language( $post_id, $lang ) {
141 - $post = get_post( $post_id );
142 - $post_type_object = get_post_type_object( $post->post_type );
388 + protected function save_language( $post_id, $post ) {
389 + // security checks are necessary to accept language modifications
390 + // as 'wp_insert_post' can be called from outside WP admin
143 391
144 - if ( current_user_can( $post_type_object->cap->edit_post, $post_id ) ) {
145 - $old_lang = $this->model->post->get_language( $post_id ); // Stores the old language
146 - $this->model->post->set_language( $post_id, $lang ); // set new language
392 + // edit post
393 + if ( isset( $_POST['post_lang_choice'] ) ) {
394 + check_admin_referer( 'pll_language', '_pll_nonce' );
395 + $this->model->post->set_language( $post_id, $lang = $this->model->get_language( $_POST['post_lang_choice'] ) );
396 + }
147 397
148 - // Checks if the new language already exists in the translation group
149 - if ( $old_lang && $old_lang->slug != $lang->slug ) {
150 - $translations = $this->model->post->get_translations( $post_id );
398 + // quick edit and bulk edit
399 + // POST for quick edit, GET for bulk edit
400 + elseif ( isset( $_REQUEST['inline_lang_choice'] ) ) {
401 + // bulk edit does not modify the language
402 + if ( isset( $_GET['bulk_edit'] ) && -1 == $_REQUEST['inline_lang_choice'] ) {
403 + check_admin_referer( 'bulk-posts' );
404 + $lang = $this->model->post->get_language( $post_id ); // get the post language for later use when saving terms
405 + }
406 + // a language is set in the language dropdown
407 + else {
408 + isset( $_GET['bulk_edit'] ) ? check_admin_referer( 'bulk-posts' ) : check_admin_referer( 'inlineeditnonce', '_inline_edit' );
151 409
152 - // If yes, separate this post from the translation group
153 - if ( array_key_exists( $lang->slug, $translations ) ) {
154 - $this->model->post->delete_translation( $post_id );
410 + $old_lang = $this->model->post->get_language( $post_id ); // stores the old language
411 + $this->model->post->set_language( $post_id, $lang = $this->model->get_language( $_REQUEST['inline_lang_choice'] ) ); // set new language
412 +
413 + // checks if the new language already exists in the translation group
414 + if ( $old_lang && $old_lang->slug != $lang->slug ) {
415 + $translations = $this->model->post->get_translations( $post_id );
416 +
417 + // if yes, separate this post from the translation group
418 + if ( array_key_exists( $lang->slug, $translations ) ) {
419 + $this->model->post->delete_translation( $post_id );
420 + }
421 +
422 + elseif ( array_key_exists( $old_lang->slug, $translations ) ) {
423 + unset( $translations[ $old_lang->slug ] );
424 + $this->model->post->save_translations( $post_id, $translations );
425 + }
155 426 }
427 + }
428 + }
156 429
157 - elseif ( array_key_exists( $old_lang->slug, $translations ) ) {
158 - unset( $translations[ $old_lang->slug ] );
159 - $this->model->post->save_translations( $post_id, $translations );
430 + // quick press
431 + // 'post-quickpress-save', 'post-quickpress-publish' = backward compatibility WP < 3.8
432 + elseif ( isset( $_REQUEST['action'] ) && in_array( $_REQUEST['action'], array( 'post-quickpress-save', 'post-quickpress-publish', 'post-quickdraft-save' ) ) ) {
433 + check_admin_referer( 'add-' . $post->post_type );
434 + $this->model->post->set_language( $post_id, $lang = $this->pref_lang ); // default language for Quick draft
435 + }
436 +
437 + else {
438 + $this->set_default_language( $post_id );
439 + }
440 +
441 + // make sure we get save terms in the right language (especially tags with same name in different languages)
442 + if ( ! empty( $lang ) ) {
443 + // FIXME quite a lot of queries in foreach
444 + foreach ( $this->model->get_translated_taxonomies() as $tax ) {
445 + $terms = get_the_terms( $post_id, $tax );
446 +
447 + if ( is_array( $terms ) ) {
448 + $newterms = array();
449 + foreach ( $terms as $term ) {
450 + // check if the term is in the correct language or if a translation exist ( mainly for default category )
451 + if ( $newterm = $this->model->term->get( $term->term_id, $lang ) ) {
452 + $newterms[] = (int) $newterm;
453 + }
454 +
455 + // or choose the correct language for tags ( initially defined by name )
456 + elseif ( $newterm = $this->model->term_exists( $term->name, $tax, $term->parent, $lang ) ) {
457 + $newterms[] = (int) $newterm; // cast is important otherwise we get 'numeric' tags
458 + }
459 +
460 + // or create the term in the correct language
461 + elseif ( ! is_wp_error( $term_info = wp_insert_term( $term->name, $tax ) ) ) {
462 + $newterms[] = (int) $term_info['term_id'];
463 + }
464 + }
465 +
466 + wp_set_object_terms( $post_id, $newterms, $tax );
160 467 }
161 468 }
162 469 }
163 470 }
@@ -162,54 +469,107 @@
162 469 }
163 470 }
164 471
165 472 /**
166 - * Save language when bulk editing a post
473 + * called when a post ( or page ) is saved, published or updated
474 + * saves languages and translations
167 475 *
168 - * @since 2.3
476 + * @since 0.1
477 + *
478 + * @param int $post_id
479 + * @param object $post
480 + * @param bool $update whether it is an update or not
169 481 */
170 - public function bulk_edit_posts() {
171 - if ( isset( $_GET['bulk_edit'], $_GET['inline_lang_choice'], $_REQUEST['post'] ) && -1 !== $_GET['inline_lang_choice'] ) { // phpcs:ignore WordPress.Security.NonceVerification
172 - check_admin_referer( 'bulk-posts' );
482 + public function save_post( $post_id, $post, $update ) {
483 + // does nothing except on post types which are filterable
484 + if ( ! $this->model->is_translated_post_type( $post->post_type ) ) {
485 + return;
486 + }
173 487
174 - if ( $lang = $this->model->get_language( sanitize_key( $_GET['inline_lang_choice'] ) ) ) {
175 - $post_ids = array_map( 'intval', (array) $_REQUEST['post'] );
176 - foreach ( $post_ids as $post_id ) {
177 - $this->inline_save_language( $post_id, $lang );
178 - }
488 + if ( $id = wp_is_post_revision( $post_id ) ) {
489 + $post_id = $id;
490 + }
491 +
492 + // capability check
493 + // as 'wp_insert_post' can be called from outside WP admin
494 + $post_type_object = get_post_type_object( $post->post_type );
495 + if ( ( $update && current_user_can( $post_type_object->cap->edit_post, $post_id ) ) || ( ! $update && current_user_can( $post_type_object->cap->create_posts ) ) ) {
496 + $this->save_language( $post_id, $post );
497 +
498 + // Make sure we are saving translations only for the main post currently being edited and not for other possible post types
499 + if ( ! empty( $GLOBALS['post_type'] ) && $post->post_type === $GLOBALS['post_type'] && isset( $_POST['post_tr_lang'] ) ) {
500 + $translations = $this->save_translations( $post_id, $_POST['post_tr_lang'] );
179 501 }
502 +
503 + /**
504 + * Fires after the post language and translations are saved
505 + *
506 + * @since 1.2
507 + *
508 + * @param int $post_id post id
509 + * @param object $post post object
510 + * @param array $translations the list of translations post ids
511 + */
512 + do_action( 'pll_save_post', $post_id, $post, empty( $translations ) ? $this->model->post->get_translations( $post_id ) : $translations );
180 513 }
514 +
515 + // attempts to set a default language even if no capability
516 + else {
517 + $this->set_default_language( $post_id );
518 + }
181 519 }
182 520
183 521 /**
184 - * Save language when inline editing a post
522 + * make sure that the post parent is in the correct language when using bulk edit
185 523 *
186 - * @since 2.3
524 + * @since 1.8
525 + *
526 + * @param int $post_parent Post parent ID.
527 + * @param int $post_id Post ID.
528 + * @param array $new_postarr Array of parsed post data.
529 + * @param array $postarr Array of sanitized, but otherwise unmodified post data.
530 + * @return int
187 531 */
188 - public function inline_edit_post() {
189 - check_admin_referer( 'inlineeditnonce', '_inline_edit' );
532 + public function wp_insert_post_parent( $post_parent, $post_id, $new_postarr, $postarr ) {
533 + if ( isset( $postarr['bulk_edit'] ) ) {
534 + check_admin_referer( 'bulk-posts' );
535 + $lang = -1 == $postarr['inline_lang_choice'] ?
536 + $this->model->post->get_language( $post_id ) :
537 + $this->model->get_language( $postarr['inline_lang_choice'] );
538 + $post_parent = $this->model->post->get_translation( $post_parent, $lang );
539 + }
540 + return $post_parent;
541 + }
190 542
191 - if ( isset( $_POST['post_ID'], $_POST['inline_lang_choice'] ) ) {
192 - $post_id = (int) $_POST['post_ID'];
193 - $lang = $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) );
194 - if ( $post_id && $lang ) {
195 - $this->inline_save_language( $post_id, $lang );
196 - }
543 + /**
544 + * called when a post, page or media is deleted
545 + * don't delete translations if this is a post revision thanks to AndyDeGroo who catched this bug
546 + * http://wordpress.org/support/topic/plugin-polylang-quick-edit-still-breaks-translation-linking-of-pages-in-072
547 + *
548 + * @since 0.1
549 + *
550 + * @param int $post_id
551 + */
552 + public function delete_post( $post_id ) {
553 + if ( ! wp_is_post_revision( $post_id ) ) {
554 + $this->model->post->delete_translation( $post_id );
197 555 }
198 556 }
199 557
200 558 /**
201 - * Sets the language attribute and text direction for Tiny MCE
559 + * filters the pages by language in the parent dropdown list in the page attributes metabox
202 560 *
203 - * @since 2.2
561 + * @since 0.6
204 562 *
205 - * @param array $mce_init TinyMCE config
206 - * @return array
563 + * @param array $dropdown_args arguments passed to wp_dropdown_pages
564 + * @param object $post
565 + * @return array modified arguments
207 566 */
208 - public function tiny_mce_before_init( $mce_init ) {
209 - if ( ! empty( $this->curlang ) ) {
210 - $mce_init['wp_lang_attr'] = $this->curlang->get_locale( 'display' );
211 - $mce_init['directionality'] = $this->curlang->is_rtl ? 'rtl' : 'ltr';
567 + public function page_attributes_dropdown_pages_args( $dropdown_args, $post ) {
568 + $dropdown_args['lang'] = isset( $_POST['lang'] ) ? $this->model->get_language( $_POST['lang'] ) : $this->model->post->get_language( $post->ID ); // ajax or not ?
569 + if ( ! $dropdown_args['lang'] ) {
570 + $dropdown_args['lang'] = $this->pref_lang;
212 571 }
213 - return $mce_init;
572 +
573 + return $dropdown_args;
214 574 }
215 575 }