PluginProbe
Polylang / 2.1.6
Polylang v2.1.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-filters-columns.php

admin-filters-columns.php in Polylang 2.1.6, at admin/admin-filters-columns.php

342 lines 12.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * adds the language column in posts and terms list tables
5 * manages quick edit and bulk edit as well
6 *
7 * @since 1.2
8 */
9 class PLL_Admin_Filters_Columns {
10 public $links, $model, $filter_lang;
11
12 /**
13 * constructor: setups filters and actions
14 *
15 * @since 1.2
16 *
17 * @param object $polylang
18 */
19 public function __construct( &$polylang ) {
20 $this->links = &$polylang->links;
21 $this->model = &$polylang->model;
22 $this->filter_lang = &$polylang->filter_lang;
23
24 // add the language and translations columns in 'All Posts', 'All Pages' and 'Media library' panels
25 foreach ( $this->model->get_translated_post_types() as $type ) {
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 );
30 }
31
32 // quick edit and bulk edit
33 add_filter( 'quick_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
34 add_filter( 'bulk_edit_custom_box', array( $this, 'quick_edit_custom_box' ), 10, 2 );
35
36 // adds the language column in the 'Categories' and 'Post Tags' tables
37 foreach ( $this->model->get_translated_taxonomies() as $tax ) {
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 );
40 }
41
42 // ajax responses to update list table rows
43 add_action( 'wp_ajax_pll_update_post_rows', array( $this, 'ajax_update_post_rows' ) );
44 add_action( 'wp_ajax_pll_update_term_rows', array( $this, 'ajax_update_term_rows' ) );
45 }
46
47 /**
48 * adds languages and translations columns in posts, pages, media, categories and tags tables
49 *
50 * @since 0.8.2
51 *
52 * @param array $columns list of table columns
53 * @param string $before the column before which we want to add our languages
54 * @return array modified list of columns
55 */
56 protected function add_column( $columns, $before ) {
57 if ( $n = array_search( $before, array_keys( $columns ) ) ) {
58 $end = array_slice( $columns, $n );
59 $columns = array_slice( $columns, 0, $n );
60 }
61
62 foreach ( $this->model->get_languages_list() as $language ) {
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 }
68
69 return isset( $end ) ? array_merge( $columns, $end ) : $columns;
70 }
71
72 /**
73 * returns the first language column in the posts, pages and media library tables
74 *
75 * @since 0.9
76 *
77 * @return string first language column name
78 */
79 protected function get_first_language_column() {
80 foreach ( $this->model->get_languages_list() as $language ) {
81 if ( empty( $this->filter_lang ) || $language->slug != $this->filter_lang->slug ) {
82 $columns[] = 'language_' . $language->slug;
83 }
84 }
85
86 return empty( $columns ) ? '' : reset( $columns );
87 }
88
89 /**
90 * adds the language and translations columns ( before the comments column ) in the posts, pages and media library tables
91 *
92 * @since 0.1
93 *
94 * @param array $columns list of posts table columns
95 * @return array modified list of columns
96 */
97 function add_post_column( $columns ) {
98 return $this->add_column( $columns, 'comments' );
99 }
100
101 /**
102 * fills the language and translations columns in the posts, pages and media library tables
103 * take care that when doing ajax inline edit, the post may not be updated in database yet
104 *
105 * @since 0.1
106 *
107 * @param string $column column name
108 * @param int $post_id
109 */
110 public function post_column( $column, $post_id ) {
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 );
113
114 if ( false === strpos( $column, 'language_' ) || ! $lang ) {
115 return;
116 }
117
118 $language = $this->model->get_language( substr( $column, 9 ) );
119
120 // hidden field containing the post language for quick edit
121 if ( $column == $this->get_first_language_column() ) {
122 printf( '<div class="hidden" id="lang_%d">%s</div>', esc_attr( $post_id ), esc_html( $lang->slug ) );
123 }
124
125 $post_type_object = get_post_type_object( get_post_type( $post_id ) );
126
127 // link to edit post ( or a translation )
128 if ( $id = $this->model->post->get( $post_id, $language ) ) {
129 // get_edit_post_link returns nothing if the user cannot edit the post
130 // thanks to Solinx. See http://wordpress.org/support/topic/feature-request-incl-code-check-for-capabilities-in-admin-screens
131 if ( $link = get_edit_post_link( $id ) ) {
132 if ( $id === $post_id ) {
133 $class = 'pll_icon_tick';
134 /* translators: accessibility text, %s is a native language name */
135 $s = sprintf( __( 'Edit this item in %s', 'polylang' ), $language->name );
136 } else {
137 $class = esc_attr( 'pll_icon_edit translation_' . $id );
138 /* translators: accessibility text, %s is a native language name */
139 $s = sprintf( __( 'Edit the translation in %s', 'polylang' ), $language->name );
140 }
141 printf(
142 '<a class="%1$s" title="%2$s" href="%3$s"><span class="screen-reader-text">%4$s</span></a>',
143 esc_attr( $class ), esc_attr( get_post( $id )->post_title ), esc_url( $link ), esc_html( $s )
144 );
145 } elseif ( $id === $post_id ) {
146 printf(
147 '<span class="pll_icon_tick"><span class="screen-reader-text">%s</span></span>',
148 /* translators: accessibility text, %s is a native language name */
149 esc_html( sprintf( __( 'This item is in %s', 'polylang' ), $language->name ) )
150 );
151 }
152 }
153 // link to add a new translation
154 else {
155 echo $this->links->new_post_translation_link( $post_id, $language );
156 }
157 }
158
159 /**
160 * quick edit & bulk edit
161 *
162 * @since 0.9
163 *
164 * @param string $column column name
165 * @param string $type either 'edit-tags' for terms list table or post type for posts list table
166 * @return string unmodified $column
167 */
168 public function quick_edit_custom_box( $column, $type ) {
169 if ( $column == $this->get_first_language_column() ) {
170
171 $elements = $this->model->get_languages_list();
172 if ( current_filter() == 'bulk_edit_custom_box' ) {
173 array_unshift( $elements, (object) array( 'slug' => -1, 'name' => __( '&mdash; No Change &mdash;' ) ) );
174 }
175
176 $dropdown = new PLL_Walker_Dropdown();
177 // the hidden field 'old_lang' allows to pass the old language to ajax request
178 printf(
179 '<fieldset class="inline-edit-col-left">
180 <div class="inline-edit-col">
181 <label class="alignleft">
182 <span class="title">%s</span>
183 %s
184 </label>
185 </div>
186 </fieldset>',
187 esc_html__( 'Language', 'polylang' ),
188 $dropdown->walk( $elements, array( 'name' => 'inline_lang_choice', 'id' => '' ) )
189 );
190 }
191 return $column;
192 }
193
194 /**
195 * adds the language column ( before the posts column ) in the 'Categories' or 'Post Tags' table
196 *
197 * @since 0.1
198 *
199 * @param array $columns list of terms table columns
200 * @return array modified list of columns
201 */
202 public function add_term_column( $columns ) {
203 return $this->add_column( $columns, 'posts' );
204 }
205
206 /**
207 * fills the language column in the 'Categories' or 'Post Tags' table
208 *
209 * @since 0.1
210 *
211 * @param string $out
212 * @param string $column column name
213 * @param int term_id
214 */
215 public function term_column( $out, $column, $term_id ) {
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 ) ) ) {
218 return $out;
219 }
220
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'];
223
224 if ( ! post_type_exists( $post_type ) || ! taxonomy_exists( $taxonomy ) ) {
225 return $out;
226 }
227
228 $term_id = (int) $term_id;
229 $language = $this->model->get_language( substr( $column, 9 ) );
230
231 if ( $column == $this->get_first_language_column() ) {
232 $out = sprintf( '<div class="hidden" id="lang_%d">%s</div>', $term_id, esc_html( $lang->slug ) );
233
234 // identify the default categories to disable the language dropdown in js
235 if ( in_array( get_option( 'default_category' ), $this->model->term->get_translations( $term_id ) ) ) {
236 $out .= sprintf( '<div class="hidden" id="default_cat_%1$d">%1$d</div>', $term_id );
237 }
238 }
239
240 // link to edit term ( or a translation )
241 if ( ( $id = $this->model->term->get( $term_id, $language ) ) && $term = get_term( $id, $taxonomy ) ) {
242 if ( $link = get_edit_term_link( $id, $taxonomy, $post_type ) ) {
243 if ( $id === $term_id ) {
244 $class = 'pll_icon_tick';
245 /* translators: accessibility text, %s is a native language name */
246 $s = sprintf( __( 'Edit this item in %s', 'polylang' ), $language->name );
247 } else {
248 $class = esc_attr( 'pll_icon_edit translation_' . $id );
249 /* translators: accessibility text, %s is a native language name */
250 $s = sprintf( __( 'Edit the translation in %s', 'polylang' ), $language->name );
251 }
252 $out .= sprintf(
253 '<a class="%1$s" title="%2$s" href="%3$s"><span class="screen-reader-text">%4$s</span></a>',
254 $class, esc_attr( $term->name ), esc_url( $link ), esc_html( $s )
255 );
256 } elseif ( $id === $term_id ) {
257 $out .= printf(
258 '<span class="pll_icon_tick"><span class="screen-reader-text">%s</span></span>',
259 /* translators: accessibility text, %s is a native language name */
260 esc_html( sprintf( __( 'This item is in %s', 'polylang' ), $language->name ) )
261 );
262 }
263 }
264
265 // link to add a new translation
266 else {
267 $out .= $this->links->new_term_translation_link( $term_id, $taxonomy, $post_type, $language );
268 }
269
270 return $out;
271 }
272
273 /**
274 * update rows of translated posts when the language is modified in quick edit
275 *
276 * @since 1.7
277 */
278 public function ajax_update_post_rows() {
279 global $wp_list_table;
280
281 if ( ! post_type_exists( $post_type = $_POST['post_type'] ) || ! $this->model->is_translated_post_type( $post_type ) ) {
282 die( 0 );
283 }
284
285 check_ajax_referer( 'inlineeditnonce', '_pll_nonce' );
286
287 $x = new WP_Ajax_Response();
288 $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );
289
290 $translations = empty( $_POST['translations'] ) ? array() : explode( ',', $_POST['translations'] ); // collect old translations
291 $translations = array_merge( $translations, array( $_POST['post_id'] ) ); // add current post
292 $translations = array_map( 'intval', $translations );
293
294 foreach ( $translations as $post_id ) {
295 $level = is_post_type_hierarchical( $post_type ) ? count( get_ancestors( $post_id, $post_type ) ) : 0;
296 if ( $post = get_post( $post_id ) ) {
297 ob_start();
298 $wp_list_table->single_row( $post, $level );
299 $data = ob_get_clean();
300 $x->add( array( 'what' => 'row', 'data' => $data, 'supplemental' => array( 'post_id' => $post_id ) ) );
301 }
302 }
303
304 $x->send();
305 }
306
307 /**
308 * update rows of translated terms when adding / deleting a translation or when the language is modified in quick edit
309 *
310 * @since 1.7
311 */
312 public function ajax_update_term_rows() {
313 global $wp_list_table;
314
315 if ( ! taxonomy_exists( $taxonomy = $_POST['taxonomy'] ) || ! $this->model->is_translated_taxonomy( $taxonomy ) ) {
316 die( 0 );
317 }
318
319 check_ajax_referer( 'pll_language', '_pll_nonce' );
320
321 $x = new WP_Ajax_Response();
322 $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) );
323
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
327 $translations = array_map( 'intval', $translations );
328
329 foreach ( $translations as $term_id ) {
330 $level = is_taxonomy_hierarchical( $taxonomy ) ? count( get_ancestors( $term_id, $taxonomy ) ) : 0;
331 if ( $tag = get_term( $term_id, $taxonomy ) ) {
332 ob_start();
333 $wp_list_table->single_row( $tag, $level );
334 $data = ob_get_clean();
335 $x->add( array( 'what' => 'row', 'data' => $data, 'supplemental' => array( 'term_id' => $term_id ) ) );
336 }
337 }
338
339 $x->send();
340 }
341 }
342