PluginProbe
Polylang / 2.7
Polylang v2.7
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / admin / admin-classic-editor.php

admin-classic-editor.php in Polylang 2.7, at admin/admin-classic-editor.php

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