PluginProbe
Polylang / 2.6
Polylang v2.6
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.6, at admin/admin-classic-editor.php

316 lines 10.1 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_id = $post_ID;
70 $post_type = get_post_type( $post_ID );
71
72 $from_post_id = isset( $_GET['from_post'] ) ? (int) $_GET['from_post'] : 0; // phpcs:ignore WordPress.Security.NonceVerification
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 array(
85 'name' => $id,
86 'class' => 'post_lang_choice tags-input',
87 'selected' => $lang ? $lang->slug : '',
88 'flag' => true,
89 )
90 );
91
92 wp_nonce_field( 'pll_language', '_pll_nonce' );
93
94 // NOTE: the class "tags-input" allows to include the field in the autosave $_POST ( see autosave.js )
95 printf(
96 '<p><strong>%1$s</strong></p>
97 <label class="screen-reader-text" for="%2$s">%1$s</label>
98 <div id="select-%3$s-language">%4$s</div>',
99 esc_html__( 'Language', 'polylang' ),
100 esc_attr( $id ),
101 ( 'attachment' === $post_type ? 'media' : 'post' ),
102 $dropdown_html // phpcs:ignore WordPress.Security.EscapeOutput
103 );
104
105 /**
106 * Fires before displaying the list of translations in the Languages metabox for posts
107 *
108 * @since 1.8
109 */
110 do_action( 'pll_before_post_translations', $post_type );
111
112 echo '<div id="post-translations" class="translations">';
113 if ( $lang ) {
114 include PLL_ADMIN_INC . '/view-translations-' . ( 'attachment' == $post_type ? 'media' : 'post' ) . '.php';
115 }
116 echo '</div>' . "\n";
117 }
118
119 /**
120 * Ajax response for changing the language in the post metabox
121 *
122 * @since 0.2
123 */
124 public function post_lang_choice() {
125 check_ajax_referer( 'pll_language', '_pll_nonce' );
126
127 if ( ! isset( $_POST['post_id'], $_POST['lang'], $_POST['post_type'] ) ) {
128 wp_die( 0 );
129 }
130
131 global $post_ID; // Obliged to use the global variable for wp_popular_terms_checklist
132 $post_id = $post_ID = (int) $_POST['post_id'];
133 $lang = $this->model->get_language( sanitize_key( $_POST['lang'] ) );
134
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'] ) ) {
162 // Not set for pages
163 foreach ( array_map( 'sanitize_key', $_POST['taxonomies'] ) as $taxname ) {
164 $taxonomy = get_taxonomy( $taxname );
165
166 ob_start();
167 $popular_ids = wp_popular_terms_checklist( $taxonomy->name );
168 $supplemental['populars'] = ob_get_contents();
169 ob_end_clean();
170
171 ob_start();
172 // Use $post_ID to remember checked terms in case we come back to the original language
173 wp_terms_checklist( $post_ID, array( 'taxonomy' => $taxonomy->name, 'popular_cats' => $popular_ids ) );
174 $supplemental['all'] = ob_get_contents();
175 ob_end_clean();
176
177 $supplemental['dropdown'] = wp_dropdown_categories(
178 array(
179 'taxonomy' => $taxonomy->name,
180 'hide_empty' => 0,
181 'name' => 'new' . $taxonomy->name . '_parent',
182 'orderby' => 'name',
183 'hierarchical' => 1,
184 'show_option_none' => '&mdash; ' . $taxonomy->labels->parent_item . ' &mdash;',
185 'echo' => 0,
186 )
187 );
188
189 $x->Add( array( 'what' => 'taxonomy', 'data' => $taxonomy->name, 'supplemental' => $supplemental ) );
190 }
191 }
192
193 // Parent dropdown list ( only for hierarchical post types )
194 if ( in_array( $post_type, get_post_types( array( 'hierarchical' => true ) ) ) ) {
195 $post = get_post( $post_ID );
196
197 // Args and filter from 'page_attributes_meta_box' in wp-admin/includes/meta-boxes.php of WP 4.2.1
198 $dropdown_args = array(
199 'post_type' => $post->post_type,
200 'exclude_tree' => $post->ID,
201 'selected' => $post->post_parent,
202 'name' => 'parent_id',
203 'show_option_none' => __( '(no parent)', 'polylang' ),
204 'sort_column' => 'menu_order, post_title',
205 'echo' => 0,
206 );
207
208 /** This filter is documented in wp-admin/includes/meta-boxes.php */
209 $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post ); // Since WP 3.3
210
211 $x->Add( array( 'what' => 'pages', 'data' => wp_dropdown_pages( $dropdown_args ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput
212 }
213
214 // Flag
215 $x->Add( array( 'what' => 'flag', 'data' => empty( $lang->flag ) ? esc_html( $lang->slug ) : $lang->flag ) );
216
217 // Sample permalink
218 $x->Add( array( 'what' => 'permalink', 'data' => get_sample_permalink_html( $post_ID ) ) );
219
220 $x->send();
221 }
222
223 /**
224 * Ajax response for input in translation autocomplete input box
225 *
226 * @since 1.5
227 */
228 public function ajax_posts_not_translated() {
229 check_ajax_referer( 'pll_language', '_pll_nonce' );
230
231 if ( ! isset( $_GET['post_type'], $_GET['post_language'], $_GET['translation_language'], $_GET['term'], $_GET['pll_post_id'] ) ) {
232 wp_die( 0 );
233 }
234
235 $post_type = sanitize_key( $_GET['post_type'] );
236
237 if ( ! post_type_exists( $post_type ) ) {
238 wp_die( 0 );
239 }
240
241 $term = wp_unslash( $_GET['term'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
242
243 $post_language = $this->model->get_language( sanitize_key( $_GET['post_language'] ) );
244 $translation_language = $this->model->get_language( sanitize_key( $_GET['translation_language'] ) );
245
246 $return = array();
247
248 $untranslated_posts = $this->model->post->get_untranslated( $post_type, $post_language, $translation_language, $term );
249
250 // format output
251 foreach ( $untranslated_posts as $post ) {
252 $return[] = array(
253 'id' => $post->ID,
254 'value' => $post->post_title,
255 'link' => $this->links->edit_post_translation_link( $post->ID ),
256 );
257 }
258
259 // Add current translation in list
260 if ( $post_id = $this->model->post->get_translation( (int) $_GET['pll_post_id'], $translation_language ) ) {
261 $post = get_post( $post_id );
262 array_unshift(
263 $return,
264 array(
265 'id' => $post_id,
266 'value' => $post->post_title,
267 'link' => $this->links->edit_post_translation_link( $post_id ),
268 )
269 );
270 }
271
272 wp_die( wp_json_encode( $return ) );
273 }
274
275 /**
276 * Filters the pages by language in the parent dropdown list in the page attributes metabox
277 *
278 * @since 0.6
279 *
280 * @param array $dropdown_args Arguments passed to wp_dropdown_pages
281 * @param object $post
282 * @return array Modified arguments
283 */
284 public function page_attributes_dropdown_pages_args( $dropdown_args, $post ) {
285 $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
286 if ( ! $dropdown_args['lang'] ) {
287 $dropdown_args['lang'] = $this->pref_lang;
288 }
289
290 return $dropdown_args;
291 }
292
293 /**
294 * Displays a notice if the user has not sufficient rights to overwrite synchronized taxonomies and metas
295 *
296 * @since 2.6
297 *
298 * @param object $post Post currently being edited
299 */
300 public function edit_form_top( $post ) {
301 if ( ! $this->model->post->current_user_can_synchronize( $post->ID ) ) {
302 ?>
303 <div class="pll-notice notice notice-warning">
304 <p>
305 <?php
306 esc_html_e( 'Some taxonomies or metadata may be synchronized with existing translations that you are not allowed to modify.', 'polylang' );
307 echo ' ';
308 esc_html_e( 'If you attempt to modify them anyway, your changes will not be saved.', 'polylang' );
309 ?>
310 </p>
311 </div>
312 <?php
313 }
314 }
315 }
316