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-columns.php +78 -126 2.7.3 → 2.0.12 View file →
@@ -1,9 +1,9 @@
1 1 <?php
2 2
3 3 /**
4 - * Adds the language column in posts and terms list tables
5 - * Manages quick edit and bulk edit as well
4 + * adds the language column in posts and terms list tables
5 + * manages quick edit and bulk edit as well
6 6 *
7 7 * @since 1.2
8 8 */
9 9 class PLL_Admin_Filters_Columns {
@@ -9,9 +9,9 @@
9 9 class PLL_Admin_Filters_Columns {
10 10 public $links, $model, $filter_lang;
11 11
12 12 /**
13 - * Constructor: setups filters and actions
13 + * constructor: setups filters and actions
14 14 *
15 15 * @since 1.2
16 16 *
17 17 * @param object $polylang
@@ -20,41 +20,38 @@
20 20 $this->links = &$polylang->links;
21 21 $this->model = &$polylang->model;
22 22 $this->filter_lang = &$polylang->filter_lang;
23 23
24 - // Hide the column of the filtered language.
25 - add_filter( 'hidden_columns', array( $this, 'hidden_columns' ) ); // Since WP 4.4.
26 -
27 - // Add the language and translations columns in 'All Posts', 'All Pages' and 'Media library' panels.
24 + // add the language and translations columns in 'All Posts', 'All Pages' and 'Media library' panels
28 25 foreach ( $this->model->get_translated_post_types() as $type ) {
29 - // Use the latest filter late as some plugins purely overwrite what's done by others :(
30 - // Specific case for media.
31 - add_filter( 'manage_' . ( 'attachment' == $type ? 'upload' : 'edit-' . $type ) . '_columns', array( $this, 'add_post_column' ), 100 );
32 - add_action( 'manage_' . ( 'attachment' == $type ? 'media' : $type . '_posts' ) . '_custom_column', array( $this, 'post_column' ), 10, 2 );
26 + // use the latest filter late as some plugins purely overwrite what's done by others :(
27 + // specific case for media
28 + add_filter( 'manage_'. ( 'attachment' == $type ? 'upload' : 'edit-'. $type ) .'_columns', array( $this, 'add_post_column' ), 100 );
29 + add_action( 'manage_'. ( 'attachment' == $type ? 'media' : $type .'_posts' ) .'_custom_column', array( $this, 'post_column' ), 10, 2 );
33 30 }
34 31
35 - // Quick edit and bulk edit.
32 + // quick edit and bulk edit
36 33 add_filter( 'quick_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
37 34 add_filter( 'bulk_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
38 35
39 - // Adds the language column in the 'Categories' and 'Post Tags' tables.
36 + // adds the language column in the 'Categories' and 'Post Tags' tables
40 37 foreach ( $this->model->get_translated_taxonomies() as $tax ) {
41 - add_filter( 'manage_edit-' . $tax . '_columns', array( $this, 'add_term_column' ) );
42 - add_filter( 'manage_' . $tax . '_custom_column', array( $this, 'term_column' ), 10, 3 );
38 + add_filter( 'manage_edit-'.$tax.'_columns', array( $this, 'add_term_column' ) );
39 + add_filter( 'manage_'.$tax.'_custom_column', array( $this, 'term_column' ), 10, 3 );
43 40 }
44 41
45 - // Ajax responses to update list table rows.
42 + // ajax responses to update list table rows
46 43 add_action( 'wp_ajax_pll_update_post_rows', array( $this, 'ajax_update_post_rows' ) );
47 44 add_action( 'wp_ajax_pll_update_term_rows', array( $this, 'ajax_update_term_rows' ) );
48 45 }
49 46
50 47 /**
51 - * Adds languages and translations columns in posts, pages, media, categories and tags tables
48 + * adds languages and translations columns in posts, pages, media, categories and tags tables
52 49 *
53 50 * @since 0.8.2
54 51 *
55 - * @param array $columns List of table columns
56 - * @param string $before The column before which we want to add our languages
52 + * @param array $columns list of table columns
53 + * @param string $before the column before which we want to add our languages
57 54 * @return array modified list of columns
58 55 */
59 56 protected function add_column( $columns, $before ) {
60 57 if ( $n = array_search( $before, array_keys( $columns ) ) ) {
@@ -62,9 +59,12 @@
62 59 $columns = array_slice( $columns, 0, $n );
63 60 }
64 61
65 62 foreach ( $this->model->get_languages_list() as $language ) {
66 - $columns[ 'language_' . $language->slug ] = $language->flag ? $language->flag . '<span class="screen-reader-text">' . esc_html( $language->name ) . '</span>' : esc_html( $language->slug );
63 + // don't add the column for the filtered language
64 + if ( empty( $this->filter_lang ) || $language->slug != $this->filter_lang->slug ) {
65 + $columns[ 'language_'.$language->slug ] = $language->flag ? $language->flag . '<span class="screen-reader-text">' . esc_html( $language->name ) . '</span>' : esc_html( $language->slug );
66 + }
67 67 }
68 68
69 69 return isset( $end ) ? array_merge( $columns, $end ) : $columns;
70 70 }
@@ -69,9 +69,9 @@
69 69 return isset( $end ) ? array_merge( $columns, $end ) : $columns;
70 70 }
71 71
72 72 /**
73 - * Returns the first language column in the posts, pages and media library tables
73 + * returns the first language column in the posts, pages and media library tables
74 74 *
75 75 * @since 0.9
76 76 *
77 77 * @return string first language column name
@@ -76,12 +76,12 @@
76 76 *
77 77 * @return string first language column name
78 78 */
79 79 protected function get_first_language_column() {
80 - $columns = array();
81 -
82 80 foreach ( $this->model->get_languages_list() as $language ) {
83 - $columns[] = 'language_' . $language->slug;
81 + if ( empty( $this->filter_lang ) || $language->slug != $this->filter_lang->slug ) {
82 + $columns[] = 'language_' . $language->slug;
83 + }
84 84 }
85 85
86 86 return empty( $columns ) ? '' : reset( $columns );
87 87 }
@@ -86,46 +86,31 @@
86 86 return empty( $columns ) ? '' : reset( $columns );
87 87 }
88 88
89 89 /**
90 - * Hide the column for the filtered language
90 + * adds the language and translations columns ( before the comments column ) in the posts, pages and media library tables
91 91 *
92 - * @since 2.7
93 - *
94 - * @param array $hidden Array of hidden columns
95 - * @return array
96 - */
97 - public function hidden_columns( $hidden ) {
98 - if ( ! empty( $this->filter_lang ) ) {
99 - $hidden[] = 'language_' . $this->filter_lang->slug;
100 - }
101 - return $hidden;
102 - }
103 -
104 - /**
105 - * Adds the language and translations columns ( before the comments column ) in the posts, pages and media library tables
106 - *
107 92 * @since 0.1
108 93 *
109 94 * @param array $columns list of posts table columns
110 95 * @return array modified list of columns
111 96 */
112 - public function add_post_column( $columns ) {
97 + function add_post_column( $columns ) {
113 98 return $this->add_column( $columns, 'comments' );
114 99 }
115 100
116 101 /**
117 - * Fills the language and translations columns in the posts, pages and media library tables
102 + * fills the language and translations columns in the posts, pages and media library tables
118 103 * take care that when doing ajax inline edit, the post may not be updated in database yet
119 104 *
120 105 * @since 0.1
121 106 *
122 - * @param string $column Column name
123 - * @param int $post_id
107 + * @param string $column column name
108 + * @param int $post_id
124 109 */
125 110 public function post_column( $column, $post_id ) {
126 - $inline = wp_doing_ajax() && isset( $_REQUEST['action'], $_POST['inline_lang_choice'] ) && 'inline-save' === $_REQUEST['action']; // phpcs:ignore WordPress.Security.NonceVerification
127 - $lang = $inline ? $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) ) : $this->model->post->get_language( $post_id ); // phpcs:ignore WordPress.Security.NonceVerification
111 + $inline = defined( 'DOING_AJAX' ) && isset( $_REQUEST['action'], $_POST['inline_lang_choice'] ) && 'inline-save' === $_REQUEST['action'];
112 + $lang = $inline ? $this->model->get_language( $_POST['inline_lang_choice'] ) : $this->model->post->get_language( $post_id );
128 113
129 114 if ( false === strpos( $column, 'language_' ) || ! $lang ) {
130 115 return;
131 116 }
@@ -131,17 +116,19 @@
131 116 }
132 117
133 118 $language = $this->model->get_language( substr( $column, 9 ) );
134 119
135 - // Hidden field containing the post language for quick edit
120 + // hidden field containing the post language for quick edit
136 121 if ( $column == $this->get_first_language_column() ) {
137 - printf( '<div class="hidden" id="lang_%d">%s</div>', intval( $post_id ), esc_html( $lang->slug ) );
122 + printf( '<div class="hidden" id="lang_%d">%s</div>', esc_attr( $post_id ), esc_html( $lang->slug ) );
138 123 }
139 124
140 - // Link to edit post ( or a translation )
125 + $post_type_object = get_post_type_object( get_post_type( $post_id ) );
126 +
127 + // link to edit post ( or a translation )
141 128 if ( $id = $this->model->post->get( $post_id, $language ) ) {
142 129 // get_edit_post_link returns nothing if the user cannot edit the post
143 - // Thanks to Solinx. See http://wordpress.org/support/topic/feature-request-incl-code-check-for-capabilities-in-admin-screens
130 + // thanks to Solinx. See http://wordpress.org/support/topic/feature-request-incl-code-check-for-capabilities-in-admin-screens
144 131 if ( $link = get_edit_post_link( $id ) ) {
145 132 if ( $id === $post_id ) {
146 133 $class = 'pll_icon_tick';
147 134 /* translators: accessibility text, %s is a native language name */
@@ -152,12 +139,9 @@
152 139 $s = sprintf( __( 'Edit the translation in %s', 'polylang' ), $language->name );
153 140 }
154 141 printf(
155 142 '<a class="%1$s" title="%2$s" href="%3$s"><span class="screen-reader-text">%4$s</span></a>',
156 - esc_attr( $class ),
157 - esc_attr( get_post( $id )->post_title ),
158 - esc_url( $link ),
159 - esc_html( $s )
143 + esc_attr( $class ), esc_attr( get_post( $id )->post_title ), esc_url( $link ), esc_html( $s )
160 144 );
161 145 } elseif ( $id === $post_id ) {
162 146 printf(
163 147 '<span class="pll_icon_tick"><span class="screen-reader-text">%s</span></span>',
@@ -162,19 +146,19 @@
162 146 printf(
163 147 '<span class="pll_icon_tick"><span class="screen-reader-text">%s</span></span>',
164 148 /* translators: accessibility text, %s is a native language name */
165 149 esc_html( sprintf( __( 'This item is in %s', 'polylang' ), $language->name ) )
166 - );
150 + );
167 151 }
168 152 }
169 - // Link to add a new translation
153 + // link to add a new translation
170 154 else {
171 - echo $this->links->new_post_translation_link( $post_id, $language ); // phpcs:ignore WordPress.Security.EscapeOutput
155 + echo $this->links->new_post_translation_link( $post_id, $language );
172 156 }
173 157 }
174 158
175 159 /**
176 - * Quick edit & bulk edit
160 + * quick edit & bulk edit
177 161 *
178 162 * @since 0.9
179 163 *
180 164 * @param string $column column name
@@ -185,13 +169,13 @@
185 169 if ( $column == $this->get_first_language_column() ) {
186 170
187 171 $elements = $this->model->get_languages_list();
188 172 if ( current_filter() == 'bulk_edit_custom_box' ) {
189 - array_unshift( $elements, (object) array( 'slug' => -1, 'name' => __( '&mdash; No Change &mdash;', 'polylang' ) ) );
173 + array_unshift( $elements, (object) array( 'slug' => -1, 'name' => __( '&mdash; No Change &mdash;' ) ) );
190 174 }
191 175
192 176 $dropdown = new PLL_Walker_Dropdown();
193 - // The hidden field 'old_lang' allows to pass the old language to ajax request
177 + // the hidden field 'old_lang' allows to pass the old language to ajax request
194 178 printf(
195 179 '<fieldset class="inline-edit-col-left">
196 180 <div class="inline-edit-col">
197 181 <label class="alignleft">
@@ -200,9 +184,9 @@
200 184 </label>
201 185 </div>
202 186 </fieldset>',
203 187 esc_html__( 'Language', 'polylang' ),
204 - $dropdown->walk( $elements, -1, array( 'name' => 'inline_lang_choice', 'id' => '' ) ) // phpcs:ignore WordPress.Security.EscapeOutput
188 + $dropdown->walk( $elements, array( 'name' => 'inline_lang_choice', 'id' => '' ) )
205 189 );
206 190 }
207 191 return $column;
208 192 }
@@ -207,9 +191,9 @@
207 191 return $column;
208 192 }
209 193
210 194 /**
211 - * Adds the language column ( before the posts column ) in the 'Categories' or 'Post Tags' table
195 + * adds the language column ( before the posts column ) in the 'Categories' or 'Post Tags' table
212 196 *
213 197 * @since 0.1
214 198 *
215 199 * @param array $columns list of terms table columns
@@ -219,38 +203,25 @@
219 203 return $this->add_column( $columns, 'posts' );
220 204 }
221 205
222 206 /**
223 - * Fills the language column in the 'Categories' or 'Post Tags' table
207 + * fills the language column in the 'Categories' or 'Post Tags' table
224 208 *
225 209 * @since 0.1
226 210 *
227 211 * @param string $out
228 - * @param string $column Column name
229 - * @param int $term_id
212 + * @param string $column column name
213 + * @param int term_id
230 214 */
231 215 public function term_column( $out, $column, $term_id ) {
232 - $inline = wp_doing_ajax() && isset( $_REQUEST['action'], $_POST['inline_lang_choice'] ) && 'inline-save-tax' === $_REQUEST['action']; // phpcs:ignore WordPress.Security.NonceVerification
233 - if ( false === strpos( $column, 'language_' ) || ! ( $lang = $inline ? $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) ) : $this->model->term->get_language( $term_id ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
216 + $inline = defined( 'DOING_AJAX' ) && isset( $_REQUEST['action'], $_POST['inline_lang_choice'] ) && 'inline-save-tax' === $_REQUEST['action'];
217 + if ( false === strpos( $column, 'language_' ) || ! ( $lang = $inline ? $this->model->get_language( $_POST['inline_lang_choice'] ) : $this->model->term->get_language( $term_id ) ) ) {
234 218 return $out;
235 219 }
236 220
237 - if ( isset( $_REQUEST['post_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
238 - $post_type = sanitize_key( $_REQUEST['post_type'] ); // phpcs:ignore WordPress.Security.NonceVerification
239 - }
221 + $post_type = isset( $GLOBALS['post_type'] ) ? $GLOBALS['post_type'] : $_REQUEST['post_type']; // 2nd case for quick edit
222 + $taxonomy = isset( $GLOBALS['taxonomy'] ) ? $GLOBALS['taxonomy'] : $_REQUEST['taxonomy'];
240 223
241 - if ( isset( $GLOBALS['post_type'] ) ) {
242 - $post_type = $GLOBALS['post_type'];
243 - }
244 -
245 - if ( isset( $_REQUEST['taxonomy'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
246 - $taxonomy = sanitize_key( $_REQUEST['taxonomy'] ); // phpcs:ignore WordPress.Security.NonceVerification
247 - }
248 -
249 - if ( isset( $GLOBALS['taxonomy'] ) ) {
250 - $taxonomy = $GLOBALS['taxonomy'];
251 - }
252 -
253 224 if ( ! post_type_exists( $post_type ) || ! taxonomy_exists( $taxonomy ) ) {
254 225 return $out;
255 226 }
256 227
@@ -257,17 +228,17 @@
257 228 $term_id = (int) $term_id;
258 229 $language = $this->model->get_language( substr( $column, 9 ) );
259 230
260 231 if ( $column == $this->get_first_language_column() ) {
261 - $out = sprintf( '<div class="hidden" id="lang_%d">%s</div>', intval( $term_id ), esc_html( $lang->slug ) );
232 + $out = sprintf( '<div class="hidden" id="lang_%d">%s</div>', $term_id, esc_html( $lang->slug ) );
262 233
263 - // Identify the default categories to disable the language dropdown in js
234 + // identify the default categories to disable the language dropdown in js
264 235 if ( in_array( get_option( 'default_category' ), $this->model->term->get_translations( $term_id ) ) ) {
265 - $out .= sprintf( '<div class="hidden" id="default_cat_%1$d">%1$d</div>', intval( $term_id ) );
236 + $out .= sprintf( '<div class="hidden" id="default_cat_%1$d">%1$d</div>', $term_id );
266 237 }
267 238 }
268 239
269 - // Link to edit term ( or a translation )
240 + // link to edit term ( or a translation )
270 241 if ( ( $id = $this->model->term->get( $term_id, $language ) ) && $term = get_term( $id, $taxonomy ) ) {
271 242 if ( $link = get_edit_term_link( $id, $taxonomy, $post_type ) ) {
272 243 if ( $id === $term_id ) {
273 244 $class = 'pll_icon_tick';
@@ -279,23 +250,20 @@
279 250 $s = sprintf( __( 'Edit the translation in %s', 'polylang' ), $language->name );
280 251 }
281 252 $out .= sprintf(
282 253 '<a class="%1$s" title="%2$s" href="%3$s"><span class="screen-reader-text">%4$s</span></a>',
283 - $class,
284 - esc_attr( $term->name ),
285 - esc_url( $link ),
286 - esc_html( $s )
254 + $class, esc_attr( $term->name ), esc_url( $link ), esc_html( $s )
287 255 );
288 256 } elseif ( $id === $term_id ) {
289 - $out .= sprintf(
257 + $out .= printf(
290 258 '<span class="pll_icon_tick"><span class="screen-reader-text">%s</span></span>',
291 259 /* translators: accessibility text, %s is a native language name */
292 260 esc_html( sprintf( __( 'This item is in %s', 'polylang' ), $language->name ) )
293 - );
261 + );
294 262 }
295 263 }
296 264
297 - // Link to add a new translation
265 + // link to add a new translation
298 266 else {
299 267 $out .= $this->links->new_term_translation_link( $term_id, $taxonomy, $post_type, $language );
300 268 }
301 269
@@ -302,36 +270,28 @@
302 270 return $out;
303 271 }
304 272
305 273 /**
306 - * Update rows of translated posts when the language is modified in quick edit
274 + * update rows of translated posts when the language is modified in quick edit
307 275 *
308 276 * @since 1.7
309 277 */
310 278 public function ajax_update_post_rows() {
311 - check_ajax_referer( 'inlineeditnonce', '_pll_nonce' );
279 + global $wp_list_table;
312 280
313 - if ( ! isset( $_POST['post_type'], $_POST['post_id'], $_POST['screen'] ) ) {
314 - wp_die( 0 );
281 + if ( ! post_type_exists( $post_type = $_POST['post_type'] ) || ! $this->model->is_translated_post_type( $post_type ) ) {
282 + die( 0 );
315 283 }
316 284
317 - $post_type = sanitize_key( $_POST['post_type'] );
285 + check_ajax_referer( 'inlineeditnonce', '_pll_nonce' );
318 286
319 - if ( ! post_type_exists( $post_type ) || ! $this->model->is_translated_post_type( $post_type ) ) {
320 - wp_die( 0 );
321 - }
322 -
323 - global $wp_list_table;
324 - $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => sanitize_key( $_POST['screen'] ) ) );
325 -
326 287 $x = new WP_Ajax_Response();
288 + $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );
327 289
328 - // Collect old translations
329 - $translations = empty( $_POST['translations'] ) ? array() : explode( ',', $_POST['translations'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
290 + $translations = empty( $_POST['translations'] ) ? array() : explode( ',', $_POST['translations'] ); // collect old translations
291 + $translations = array_merge( $translations, array( $_POST['post_id'] ) ); // add current post
330 292 $translations = array_map( 'intval', $translations );
331 293
332 - $translations = array_merge( $translations, array( (int) $_POST['post_id'] ) ); // Add current post
333 -
334 294 foreach ( $translations as $post_id ) {
335 295 $level = is_post_type_hierarchical( $post_type ) ? count( get_ancestors( $post_id, $post_type ) ) : 0;
336 296 if ( $post = get_post( $post_id ) ) {
337 297 ob_start();
@@ -344,36 +304,28 @@
344 304 $x->send();
345 305 }
346 306
347 307 /**
348 - * Update rows of translated terms when adding / deleting a translation or when the language is modified in quick edit
308 + * update rows of translated terms when adding / deleting a translation or when the language is modified in quick edit
349 309 *
350 310 * @since 1.7
351 311 */
352 312 public function ajax_update_term_rows() {
353 - check_ajax_referer( 'pll_language', '_pll_nonce' );
313 + global $wp_list_table;
354 314
355 - if ( ! isset( $_POST['taxonomy'], $_POST['term_id'], $_POST['screen'] ) ) {
356 - wp_die( 0 );
315 + if ( ! taxonomy_exists( $taxonomy = $_POST['taxonomy'] ) || ! $this->model->is_translated_taxonomy( $taxonomy ) ) {
316 + die( 0 );
357 317 }
358 318
359 - $taxonomy = sanitize_key( $_POST['taxonomy'] );
319 + check_ajax_referer( 'pll_language', '_pll_nonce' );
360 320
361 - if ( ! taxonomy_exists( $taxonomy ) || ! $this->model->is_translated_taxonomy( $taxonomy ) ) {
362 - wp_die( 0 );
363 - }
364 -
365 - global $wp_list_table;
366 - $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => sanitize_key( $_POST['screen'] ) ) );
367 -
368 321 $x = new WP_Ajax_Response();
322 + $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) );
369 323
370 - // Collect old translations
371 - $translations = empty( $_POST['translations'] ) ? array() : explode( ',', $_POST['translations'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
324 + $translations = empty( $_POST['translations'] ) ? array() : explode( ',', $_POST['translations'] ); // collect old translations
325 + $translations = array_merge( $translations, $this->model->term->get_translations( (int) $_POST['term_id'] ) ); // add current translations
326 + $translations = array_unique( $translations ); // remove doublons
372 327 $translations = array_map( 'intval', $translations );
373 -
374 - $translations = array_merge( $translations, $this->model->term->get_translations( (int) $_POST['term_id'] ) ); // Add current translations
375 - $translations = array_unique( $translations ); // Remove duplicates
376 328
377 329 foreach ( $translations as $term_id ) {
378 330 $level = is_taxonomy_hierarchical( $taxonomy ) ? count( get_ancestors( $term_id, $taxonomy ) ) : 0;
379 331 if ( $tag = get_term( $term_id, $taxonomy ) ) {