PluginProbe
Polylang / 2.5
Polylang v2.5
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-classic-editor.php +115 -196 3.0.22.5 View file →
@@ -1,8 +1,5 @@
1 1 <?php
2 -/**
3 - * @package Polylang
4 - */
5 2
6 3 /**
7 4 * Manages filters and actions related to the classic editor
8 5 *
@@ -8,33 +5,11 @@
8 5 *
9 6 * @since 2.4
10 7 */
11 8 class PLL_Admin_Classic_Editor {
12 - /**
13 - * @var PLL_Model
14 - */
15 - public $model;
9 + public $model, $links, $curlang, $pref_lang;
16 10
17 11 /**
18 - * @var PLL_Admin_Links
19 - */
20 - public $links;
21 -
22 - /**
23 - * Current language (used to filter the content).
24 - *
25 - * @var PLL_Language
26 - */
27 - public $curlang;
28 -
29 - /**
30 - * Preferred language to assign to new contents.
31 - *
32 - * @var PLL_Language
33 - */
34 - public $pref_lang;
35 -
36 - /**
37 12 * Constructor: setups filters and actions
38 13 *
39 14 * @since 2.4
40 15 *
@@ -46,9 +21,9 @@
46 21 $this->curlang = &$polylang->curlang;
47 22 $this->pref_lang = &$polylang->pref_lang;
48 23
49 24 // Adds the Languages box in the 'Edit Post' and 'Edit Page' panels
50 - add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
25 + add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 10, 2 );
51 26
52 27 // Ajax response for changing the language in the post metabox
53 28 add_action( 'wp_ajax_post_lang_choice', array( $this, 'post_lang_choice' ) );
54 29 add_action( 'wp_ajax_pll_posts_not_translated', array( $this, 'ajax_posts_not_translated' ) );
@@ -54,11 +29,8 @@
54 29 add_action( 'wp_ajax_pll_posts_not_translated', array( $this, 'ajax_posts_not_translated' ) );
55 30
56 31 // Filters the pages by language in the parent dropdown list in the page attributes metabox
57 32 add_filter( 'page_attributes_dropdown_pages_args', array( $this, 'page_attributes_dropdown_pages_args' ), 10, 2 );
58 -
59 - // Notice
60 - add_action( 'edit_form_top', array( $this, 'edit_form_top' ) );
61 33 }
62 34
63 35 /**
64 36 * Adds the Language box in the 'Edit Post' and 'Edit Page' panels ( as well as in custom post types panels )
@@ -65,23 +37,13 @@
65 37 *
66 38 * @since 0.1
67 39 *
68 40 * @param string $post_type Current post type
69 - * @return void
41 + * @param object $post Current post
70 42 */
71 - public function add_meta_boxes( $post_type ) {
43 + public function add_meta_boxes( $post_type, $post ) {
72 44 if ( $this->model->is_translated_post_type( $post_type ) ) {
73 - add_meta_box(
74 - 'ml_box',
75 - __( 'Languages', 'polylang' ),
76 - array( $this, 'post_language' ),
77 - $post_type,
78 - 'side',
79 - 'high',
80 - array(
81 - '__back_compat_meta_box' => pll_use_block_editor_plugin(),
82 - )
83 - );
45 + add_meta_box( 'ml_box', __( 'Languages', 'polylang' ), array( $this, 'post_language' ), $post_type, 'side', 'high' );
84 46 }
85 47 }
86 48
87 49 /**
@@ -87,37 +49,20 @@
87 49 /**
88 50 * Displays the Languages metabox in the 'Edit Post' and 'Edit Page' panels
89 51 *
90 52 * @since 0.1
91 - *
92 - * @return void
93 53 */
94 54 public function post_language() {
95 55 global $post_ID;
56 + $post_id = $post_ID;
96 57 $post_type = get_post_type( $post_ID );
97 58
98 - // phpcs:ignore WordPress.Security.NonceVerification, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
99 - $from_post_id = isset( $_GET['from_post'] ) ? (int) $_GET['from_post'] : 0;
100 -
101 59 $lang = ( $lg = $this->model->post->get_language( $post_ID ) ) ? $lg :
102 - ( isset( $_GET['new_lang'] ) ? $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ) : // phpcs:ignore WordPress.Security.NonceVerification
60 + ( isset( $_GET['new_lang'] ) ? $this->model->get_language( $_GET['new_lang'] ) :
103 61 $this->pref_lang );
104 62
105 63 $dropdown = new PLL_Walker_Dropdown();
106 64
107 - $id = ( 'attachment' === $post_type ) ? sprintf( 'attachments[%d][language]', (int) $post_ID ) : 'post_lang_choice';
108 -
109 - $dropdown_html = $dropdown->walk(
110 - $this->model->get_languages_list(),
111 - -1,
112 - array(
113 - 'name' => $id,
114 - 'class' => 'post_lang_choice tags-input',
115 - 'selected' => $lang ? $lang->slug : '',
116 - 'flag' => true,
117 - )
118 - );
119 -
120 65 wp_nonce_field( 'pll_language', '_pll_nonce' );
121 66
122 67 // NOTE: the class "tags-input" allows to include the field in the autosave $_POST ( see autosave.js )
123 68 printf(
@@ -124,11 +69,19 @@
124 69 '<p><strong>%1$s</strong></p>
125 70 <label class="screen-reader-text" for="%2$s">%1$s</label>
126 71 <div id="select-%3$s-language">%4$s</div>',
127 72 esc_html__( 'Language', 'polylang' ),
128 - esc_attr( $id ),
129 - ( 'attachment' === $post_type ? 'media' : 'post' ),
130 - $dropdown_html // phpcs:ignore WordPress.Security.EscapeOutput
73 + $id = ( 'attachment' === $post_type ) ? sprintf( 'attachments[%d][language]', $post_ID ) : 'post_lang_choice',
74 + 'attachment' === $post_type ? 'media' : 'post',
75 + $dropdown->walk(
76 + $this->model->get_languages_list(),
77 + array(
78 + 'name' => $id,
79 + 'class' => 'post_lang_choice tags-input',
80 + 'selected' => $lang ? $lang->slug : '',
81 + 'flag' => true,
82 + )
83 + )
131 84 );
132 85
133 86 /**
134 87 * Fires before displaying the list of translations in the Languages metabox for posts
@@ -138,13 +91,9 @@
138 91 do_action( 'pll_before_post_translations', $post_type );
139 92
140 93 echo '<div id="post-translations" class="translations">';
141 94 if ( $lang ) {
142 - if ( 'attachment' === $post_type ) {
143 - include __DIR__ . '/view-translations-media.php';
144 - } else {
145 - include __DIR__ . '/view-translations-post.php';
146 - }
95 + include PLL_ADMIN_INC . '/view-translations-' . ( 'attachment' == $post_type ? 'media' : 'post' ) . '.php';
147 96 }
148 97 echo '</div>' . "\n";
149 98 }
150 99
@@ -151,33 +100,18 @@
151 100 /**
152 101 * Ajax response for changing the language in the post metabox
153 102 *
154 103 * @since 0.2
155 - *
156 - * @return void
157 104 */
158 105 public function post_lang_choice() {
159 106 check_ajax_referer( 'pll_language', '_pll_nonce' );
160 107
161 - if ( ! isset( $_POST['post_id'], $_POST['lang'], $_POST['post_type'] ) ) {
162 - wp_die( 0 );
163 - }
164 -
165 108 global $post_ID; // Obliged to use the global variable for wp_popular_terms_checklist
166 - $post_ID = (int) $_POST['post_id'];
167 - $lang = $this->model->get_language( sanitize_key( $_POST['lang'] ) );
168 - $post_type = sanitize_key( $_POST['post_type'] );
109 + $post_id = $post_ID = (int) $_POST['post_id'];
110 + $lang = $this->model->get_language( $_POST['lang'] );
169 111
170 - if ( empty( $lang ) || ! post_type_exists( $post_type ) ) {
171 - wp_die( 0 );
172 - }
173 -
112 + $post_type = $_POST['post_type'];
174 113 $post_type_object = get_post_type_object( $post_type );
175 -
176 - if ( empty( $post_type_object ) ) {
177 - wp_die( 0 );
178 - }
179 -
180 114 if ( ! current_user_can( $post_type_object->cap->edit_post, $post_ID ) ) {
181 115 wp_die( -1 );
182 116 }
183 117
@@ -188,49 +122,44 @@
188 122 $translations = array_diff( $translations, array( $post_ID ) );
189 123 $this->model->post->save_translations( $post_ID, $translations );
190 124
191 125 ob_start();
192 - if ( 'attachment' === $post_type ) {
193 - include __DIR__ . '/view-translations-media.php';
194 - } else {
195 - include __DIR__ . '/view-translations-post.php';
126 + if ( $lang ) {
127 + include PLL_ADMIN_INC . '/view-translations-' . ( 'attachment' == $post_type ? 'media' : 'post' ) . '.php';
196 128 }
197 129 $x = new WP_Ajax_Response( array( 'what' => 'translations', 'data' => ob_get_contents() ) );
198 130 ob_end_clean();
199 131
200 132 // Categories
201 - if ( isset( $_POST['taxonomies'] ) ) { // Not set for pages
202 - $supplemental = array();
203 -
204 - foreach ( array_map( 'sanitize_key', $_POST['taxonomies'] ) as $taxname ) {
133 + if ( isset( $_POST['taxonomies'] ) ) {
134 + // Not set for pages
135 + foreach ( $_POST['taxonomies'] as $taxname ) {
205 136 $taxonomy = get_taxonomy( $taxname );
206 137
207 - if ( ! empty( $taxonomy ) ) {
208 - ob_start();
209 - $popular_ids = wp_popular_terms_checklist( $taxonomy->name );
210 - $supplemental['populars'] = ob_get_contents();
211 - ob_end_clean();
138 + ob_start();
139 + $popular_ids = wp_popular_terms_checklist( $taxonomy->name );
140 + $supplemental['populars'] = ob_get_contents();
141 + ob_end_clean();
212 142
213 - ob_start();
214 - // Use $post_ID to remember checked terms in case we come back to the original language
215 - wp_terms_checklist( $post_ID, array( 'taxonomy' => $taxonomy->name, 'popular_cats' => $popular_ids ) );
216 - $supplemental['all'] = ob_get_contents();
217 - ob_end_clean();
143 + ob_start();
144 + // Use $post_ID to remember checked terms in case we come back to the original language
145 + wp_terms_checklist( $post_ID, array( 'taxonomy' => $taxonomy->name, 'popular_cats' => $popular_ids ) );
146 + $supplemental['all'] = ob_get_contents();
147 + ob_end_clean();
218 148
219 - $supplemental['dropdown'] = wp_dropdown_categories(
220 - array(
221 - 'taxonomy' => $taxonomy->name,
222 - 'hide_empty' => 0,
223 - 'name' => 'new' . $taxonomy->name . '_parent',
224 - 'orderby' => 'name',
225 - 'hierarchical' => 1,
226 - 'show_option_none' => '&mdash; ' . $taxonomy->labels->parent_item . ' &mdash;',
227 - 'echo' => 0,
228 - )
229 - );
149 + $supplemental['dropdown'] = wp_dropdown_categories(
150 + array(
151 + 'taxonomy' => $taxonomy->name,
152 + 'hide_empty' => 0,
153 + 'name' => 'new' . $taxonomy->name . '_parent',
154 + 'orderby' => 'name',
155 + 'hierarchical' => 1,
156 + 'show_option_none' => '&mdash; ' . $taxonomy->labels->parent_item . ' &mdash;',
157 + 'echo' => 0,
158 + )
159 + );
230 160
231 - $x->Add( array( 'what' => 'taxonomy', 'data' => $taxonomy->name, 'supplemental' => $supplemental ) );
232 - }
161 + $x->Add( array( 'what' => 'taxonomy', 'data' => $taxonomy->name, 'supplemental' => $supplemental ) );
233 162 }
234 163 }
235 164
236 165 // Parent dropdown list ( only for hierarchical post types )
@@ -236,25 +165,23 @@
236 165 // Parent dropdown list ( only for hierarchical post types )
237 166 if ( in_array( $post_type, get_post_types( array( 'hierarchical' => true ) ) ) ) {
238 167 $post = get_post( $post_ID );
239 168
240 - if ( ! empty( $post ) ) {
241 - // Args and filter from 'page_attributes_meta_box' in wp-admin/includes/meta-boxes.php of WP 4.2.1
242 - $dropdown_args = array(
243 - 'post_type' => $post->post_type,
244 - 'exclude_tree' => $post->ID,
245 - 'selected' => $post->post_parent,
246 - 'name' => 'parent_id',
247 - 'show_option_none' => __( '(no parent)', 'polylang' ),
248 - 'sort_column' => 'menu_order, post_title',
249 - 'echo' => 0,
250 - );
169 + // Args and filter from 'page_attributes_meta_box' in wp-admin/includes/meta-boxes.php of WP 4.2.1
170 + $dropdown_args = array(
171 + 'post_type' => $post->post_type,
172 + 'exclude_tree' => $post->ID,
173 + 'selected' => $post->post_parent,
174 + 'name' => 'parent_id',
175 + 'show_option_none' => __( '(no parent)' ),
176 + 'sort_column' => 'menu_order, post_title',
177 + 'echo' => 0,
178 + );
251 179
252 - /** This filter is documented in wp-admin/includes/meta-boxes.php */
253 - $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post ); // Since WP 3.3
180 + /** This filter is documented in wp-admin/includes/meta-boxes.php */
181 + $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post ); // Since WP 3.3
254 182
255 - $x->Add( array( 'what' => 'pages', 'data' => wp_dropdown_pages( $dropdown_args ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput
256 - }
183 + $x->Add( array( 'what' => 'pages', 'data' => wp_dropdown_pages( $dropdown_args ) ) );
257 184 }
258 185
259 186 // Flag
260 187 $x->Add( array( 'what' => 'flag', 'data' => empty( $lang->flag ) ? esc_html( $lang->slug ) : $lang->flag ) );
@@ -268,99 +195,91 @@
268 195 /**
269 196 * Ajax response for input in translation autocomplete input box
270 197 *
271 198 * @since 1.5
272 - *
273 - * @return void
274 199 */
275 200 public function ajax_posts_not_translated() {
276 201 check_ajax_referer( 'pll_language', '_pll_nonce' );
277 202
278 - if ( ! isset( $_GET['post_type'], $_GET['post_language'], $_GET['translation_language'], $_GET['term'], $_GET['pll_post_id'] ) ) {
279 - wp_die( 0 );
203 + if ( ! post_type_exists( $_GET['post_type'] ) ) {
204 + die( 0 );
280 205 }
281 206
282 - $post_type = sanitize_key( $_GET['post_type'] );
207 + $post_language = $this->model->get_language( $_GET['post_language'] );
208 + $translation_language = $this->model->get_language( $_GET['translation_language'] );
283 209
284 - if ( ! post_type_exists( $post_type ) ) {
285 - wp_die( 0 );
286 - }
210 + // Don't order by title: see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
211 + $args = array(
212 + 's' => wp_unslash( $_GET['term'] ),
213 + 'suppress_filters' => 0, // To make the post_fields filter work
214 + 'lang' => 0, // Avoid admin language filter
215 + 'numberposts' => 20, // Limit to 20 posts
216 + 'post_status' => 'any',
217 + 'post_type' => $_GET['post_type'],
218 + 'tax_query' => array(
219 + array(
220 + 'taxonomy' => 'language',
221 + 'field' => 'term_taxonomy_id', // WP 3.5+
222 + 'terms' => $translation_language->term_taxonomy_id,
223 + ),
224 + ),
225 + );
287 226
288 - $term = wp_unslash( $_GET['term'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
227 + /**
228 + * Filter the query args when auto suggesting untranslated posts in the Languages metabox
229 + * This should help plugins to fix some edge cases
230 + *
231 + * @see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
232 + *
233 + * @since 1.7
234 + *
235 + * @param array $args WP_Query arguments
236 + */
237 + $args = apply_filters( 'pll_ajax_posts_not_translated_args', $args );
238 + $posts = get_posts( $args );
289 239
290 - $post_language = $this->model->get_language( sanitize_key( $_GET['post_language'] ) );
291 - $translation_language = $this->model->get_language( sanitize_key( $_GET['translation_language'] ) );
292 -
293 240 $return = array();
294 241
295 - $untranslated_posts = $this->model->post->get_untranslated( $post_type, $post_language, $translation_language, $term );
296 -
297 - // format output
298 - foreach ( $untranslated_posts as $post ) {
299 - $return[] = array(
300 - 'id' => $post->ID,
301 - 'value' => $post->post_title,
302 - 'link' => $this->links->edit_post_translation_link( $post->ID ),
303 - );
242 + foreach ( $posts as $key => $post ) {
243 + if ( ! $this->model->post->get_translation( $post->ID, $post_language ) ) {
244 + $return[] = array(
245 + 'id' => $post->ID,
246 + 'value' => $post->post_title,
247 + 'link' => $this->links->edit_post_translation_link( $post->ID ),
248 + );
249 + }
304 250 }
305 251
306 252 // Add current translation in list
307 253 if ( $post_id = $this->model->post->get_translation( (int) $_GET['pll_post_id'], $translation_language ) ) {
308 254 $post = get_post( $post_id );
309 -
310 - if ( ! empty( $post ) ) {
311 - array_unshift(
312 - $return,
313 - array(
314 - 'id' => $post_id,
315 - 'value' => $post->post_title,
316 - 'link' => $this->links->edit_post_translation_link( $post_id ),
317 - )
318 - );
319 - }
255 + array_unshift(
256 + $return,
257 + array(
258 + 'id' => $post_id,
259 + 'value' => $post->post_title,
260 + 'link' => $this->links->edit_post_translation_link( $post_id ),
261 + )
262 + );
320 263 }
321 264
322 - wp_die( wp_json_encode( $return ) );
265 + wp_die( json_encode( $return ) );
323 266 }
324 267
325 268 /**
326 - * Filters the pages by language in the parent dropdown list in the page attributes metabox.
269 + * Filters the pages by language in the parent dropdown list in the page attributes metabox
327 270 *
328 271 * @since 0.6
329 272 *
330 - * @param array $dropdown_args Arguments passed to wp_dropdown_pages().
331 - * @param WP_Post $post The page being edited.
332 - * @return array Modified arguments.
273 + * @param array $dropdown_args Arguments passed to wp_dropdown_pages
274 + * @param object $post
275 + * @return array Modified arguments
333 276 */
334 277 public function page_attributes_dropdown_pages_args( $dropdown_args, $post ) {
335 - $dropdown_args['lang'] = isset( $_POST['lang'] ) ? $this->model->get_language( sanitize_key( $_POST['lang'] ) ) : $this->model->post->get_language( $post->ID ); // phpcs:ignore WordPress.Security.NonceVerification
278 + $dropdown_args['lang'] = isset( $_POST['lang'] ) ? $this->model->get_language( $_POST['lang'] ) : $this->model->post->get_language( $post->ID ); // ajax or not ?
336 279 if ( ! $dropdown_args['lang'] ) {
337 280 $dropdown_args['lang'] = $this->pref_lang;
338 281 }
339 282
340 283 return $dropdown_args;
341 - }
342 -
343 - /**
344 - * Displays a notice if the user has not sufficient rights to overwrite synchronized taxonomies and metas.
345 - *
346 - * @since 2.6
347 - *
348 - * @param WP_Post $post the post currently being edited.
349 - * @return void
350 - */
351 - public function edit_form_top( $post ) {
352 - if ( ! $this->model->post->current_user_can_synchronize( $post->ID ) ) {
353 - ?>
354 - <div class="pll-notice notice notice-warning">
355 - <p>
356 - <?php
357 - esc_html_e( 'Some taxonomies or metadata may be synchronized with existing translations that you are not allowed to modify.', 'polylang' );
358 - echo ' ';
359 - esc_html_e( 'If you attempt to modify them anyway, your changes will not be saved.', 'polylang' );
360 - ?>
361 - </p>
362 - </div>
363 - <?php
364 - }
365 284 }
366 285 }