PLL_Admin_Filters_Columns

Adds the language column in posts and terms list tables manages quick edit and bulk edit as well.

Defined (1)

The class is defined in the following location(s).

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