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 -86 2.7.32.0.12 View file →
@@ -1,16 +1,16 @@
1 1 <?php
2 2
3 3 /**
4 - * Manages filters and actions related to posts on admin side
4 + * manages filters and actions related to posts on admin side
5 5 *
6 6 * @since 1.2
7 7 */
8 8 class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
9 - public $curlang;
9 + public $options, $curlang;
10 10
11 11 /**
12 - * Constructor: setups filters and actions
12 + * constructor: setups filters and actions
13 13 *
14 14 * @since 1.2
15 15 *
16 16 * @param object $polylang
@@ -16,28 +16,39 @@
16 16 * @param object $polylang
17 17 */
18 18 public function __construct( &$polylang ) {
19 19 parent::__construct( $polylang );
20 + $this->options = &$polylang->options;
20 21 $this->curlang = &$polylang->curlang;
21 22
22 23 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
23 24
24 - // Filters posts, pages and media by language
25 + // filters posts, pages and media by language
25 26 add_action( 'parse_query', array( $this, 'parse_query' ) );
26 27
27 - // Adds actions and filters related to languages when creating, saving or deleting posts and pages
28 - add_action( 'load-post.php', array( $this, 'edit_post' ) );
29 - add_action( 'load-edit.php', array( $this, 'bulk_edit_posts' ) );
30 - 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 );
31 30
32 - // Sets the language in Tiny MCE
33 - 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 );
34 45 }
35 46
36 47 /**
37 - * 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
38 49 * to filter the category checklist per post language in quick edit
39 - * Outputs a javascript list of pages ordered by language
50 + * outputs a javascript list of pages ordered by language
40 51 * to filter the parent dropdown per post language in quick edit
41 52 *
42 53 * @since 1.7
43 54 */
@@ -43,12 +54,11 @@
43 54 */
44 55 public function admin_enqueue_scripts() {
45 56 $screen = get_current_screen();
46 57
47 - // Hierarchical taxonomies
58 + //hierarchical taxonomies
48 59 if ( 'edit' == $screen->base && $taxonomies = get_object_taxonomies( $screen->post_type, 'object' ) ) {
49 - // Get translated hierarchical taxonomies
50 - $hierarchical_taxonomies = array();
60 + // get translated hierarchical taxonomies
51 61 foreach ( $taxonomies as $taxonomy ) {
52 62 if ( $taxonomy->hierarchical && $taxonomy->show_in_quick_edit && $this->model->is_translated_taxonomy( $taxonomy->name ) ) {
53 63 $hierarchical_taxonomies[] = $taxonomy->name;
54 64 }
@@ -54,10 +64,9 @@
54 64 }
55 65 }
56 66
57 67 if ( ! empty( $hierarchical_taxonomies ) ) {
58 - $terms = get_terms( $hierarchical_taxonomies, array( 'get' => 'all' ) );
59 - $term_languages = array();
68 + $terms = get_terms( $hierarchical_taxonomies, array( 'get' => 'all' ) );
60 69
61 70 foreach ( $terms as $term ) {
62 71 if ( $lang = $this->model->term->get_language( $term->term_id ) ) {
63 72 $term_languages[ $lang->slug ][ $term->taxonomy ][] = $term->term_id;
@@ -63,9 +72,9 @@
63 72 $term_languages[ $lang->slug ][ $term->taxonomy ][] = $term->term_id;
64 73 }
65 74 }
66 75
67 - // Send all these data to javascript
76 + // send all these data to javascript
68 77 if ( ! empty( $term_languages ) ) {
69 78 wp_localize_script( 'pll_post', 'pll_term_languages', $term_languages );
70 79 }
71 80 }
@@ -70,12 +79,11 @@
70 79 }
71 80 }
72 81 }
73 82
74 - // Hierarchical post types
83 + // hierarchical post types
75 84 if ( 'edit' == $screen->base && is_post_type_hierarchical( $screen->post_type ) ) {
76 - $pages = get_pages();
77 - $page_languages = array();
85 + $pages = get_pages();
78 86
79 87 foreach ( $pages as $page ) {
80 88 if ( $lang = $this->model->post->get_language( $page->ID ) ) {
81 89 $page_languages[ $lang->slug ][] = $page->ID;
@@ -81,9 +89,9 @@
81 89 $page_languages[ $lang->slug ][] = $page->ID;
82 90 }
83 91 }
84 92
85 - // Send all these data to javascript
93 + // send all these data to javascript
86 94 if ( ! empty( $page_languages ) ) {
87 95 wp_localize_script( 'pll_post', 'pll_page_languages', $page_languages );
88 96 }
89 97 }
@@ -89,9 +97,9 @@
89 97 }
90 98 }
91 99
92 100 /**
93 - * Filters posts, pages and media by language
101 + * filters posts, pages and media by language
94 102 *
95 103 * @since 0.1
96 104 *
97 105 * @param object $query a WP_Query object
@@ -96,63 +104,367 @@
96 104 *
97 105 * @param object $query a WP_Query object
98 106 */
99 107 public function parse_query( $query ) {
100 - $pll_query = new PLL_Query( $query, $this->model );
101 - $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 + }
102 154 }
103 155
104 156 /**
105 - * 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
106 159 *
107 - * @since 2.3
160 + * @since 0.1
161 + *
162 + * @param string $post_type
108 163 */
109 - public function edit_post() {
110 - if ( isset( $_POST['post_lang_choice'], $_POST['post_ID'] ) && $post_id = (int) $_POST['post_ID'] ) { // phpcs:ignore WordPress.Security.NonceVerification
111 - 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 + }
112 168
113 - $post = get_post( $post_id );
114 - $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 + }
115 174
116 - if ( current_user_can( $post_type_object->cap->edit_post, $post_id ) ) {
117 - $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 );
118 184
119 - if ( isset( $_POST['post_tr_lang'] ) ) {
120 - $this->save_translations( $post_id, array_map( 'absint', $_POST['post_tr_lang'] ) );
121 - }
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 ) );
122 278 }
123 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();
124 309 }
125 310
126 311 /**
127 - * Save language when inline editing or bulk editing a post
128 - * Fix translations if necessary
312 + * ajax response for input in translation autocomplete input box
129 313 *
130 - * @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
131 382 *
132 - * @param int $post_id Post ID
133 - * @param object $lang Language
383 + * @since 1.5
384 + *
385 + * @param int $post_id
386 + * @param array $post
134 387 */
135 - protected function inline_save_language( $post_id, $lang ) {
136 - $post = get_post( $post_id );
137 - $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
138 391
139 - if ( current_user_can( $post_type_object->cap->edit_post, $post_id ) ) {
140 - $old_lang = $this->model->post->get_language( $post_id ); // Stores the old language
141 - $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 + }
142 397
143 - // Checks if the new language already exists in the translation group
144 - if ( $old_lang && $old_lang->slug != $lang->slug ) {
145 - $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' );
146 409
147 - // If yes, separate this post from the translation group
148 - if ( array_key_exists( $lang->slug, $translations ) ) {
149 - $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 + }
150 426 }
427 + }
428 + }
151 429
152 - elseif ( array_key_exists( $old_lang->slug, $translations ) ) {
153 - unset( $translations[ $old_lang->slug ] );
154 - $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 );
155 467 }
156 468 }
157 469 }
158 470 }
@@ -157,54 +469,107 @@
157 469 }
158 470 }
159 471
160 472 /**
161 - * Save language when bulk editing a post
473 + * called when a post ( or page ) is saved, published or updated
474 + * saves languages and translations
162 475 *
163 - * @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
164 481 */
165 - public function bulk_edit_posts() {
166 - if ( isset( $_GET['bulk_edit'], $_GET['inline_lang_choice'], $_REQUEST['post'] ) && -1 !== $_GET['inline_lang_choice'] ) { // phpcs:ignore WordPress.Security.NonceVerification
167 - 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 + }
168 487
169 - if ( $lang = $this->model->get_language( sanitize_key( $_GET['inline_lang_choice'] ) ) ) {
170 - $post_ids = array_map( 'intval', (array) $_REQUEST['post'] );
171 - foreach ( $post_ids as $post_id ) {
172 - $this->inline_save_language( $post_id, $lang );
173 - }
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'] );
174 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 );
175 513 }
514 +
515 + // attempts to set a default language even if no capability
516 + else {
517 + $this->set_default_language( $post_id );
518 + }
176 519 }
177 520
178 521 /**
179 - * Save language when inline editing a post
522 + * make sure that the post parent is in the correct language when using bulk edit
180 523 *
181 - * @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
182 531 */
183 - public function inline_edit_post() {
184 - 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 + }
185 542
186 - if ( isset( $_POST['post_ID'], $_POST['inline_lang_choice'] ) ) {
187 - $post_id = (int) $_POST['post_ID'];
188 - $lang = $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) );
189 - if ( $post_id && $lang ) {
190 - $this->inline_save_language( $post_id, $lang );
191 - }
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 );
192 555 }
193 556 }
194 557
195 558 /**
196 - * 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
197 560 *
198 - * @since 2.2
561 + * @since 0.6
199 562 *
200 - * @param array $mce_init TinyMCE config
201 - * @return array
563 + * @param array $dropdown_args arguments passed to wp_dropdown_pages
564 + * @param object $post
565 + * @return array modified arguments
202 566 */
203 - public function tiny_mce_before_init( $mce_init ) {
204 - if ( ! empty( $this->curlang ) ) {
205 - $mce_init['wp_lang_attr'] = $this->curlang->get_locale( 'display' );
206 - $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;
207 571 }
208 - return $mce_init;
572 +
573 + return $dropdown_args;
209 574 }
210 575 }