PluginProbe
Polylang / 1.9.2
Polylang v1.9.2
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 / settings / table-string.php

table-string.php in Polylang 1.9.2, at settings/table-string.php

328 lines 9.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! class_exists( 'WP_List_Table' ) ) {
4 require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); // since WP 3.1
5 }
6
7 /**
8 * A class to create the strings translations table
9 * Thanks to Matt Van Andel ( http://www.mattvanandel.com ) for its plugin "Custom List Table Example" !
10 *
11 * @since 0.6
12 */
13 class PLL_Table_String extends WP_List_Table {
14 protected $languages, $strings, $groups, $selected_group;
15
16 /**
17 * Constructor
18 *
19 * @since 0.6
20 *
21 * @param array $languages list of languages
22 */
23 function __construct( $languages ) {
24 parent::__construct( array(
25 'plural' => 'Strings translations', // do not translate ( used for css class )
26 'ajax' => false,
27 ) );
28
29 $this->languages = $languages;
30 $this->strings = PLL_Admin_Strings::get_strings();
31 $this->groups = array_unique( wp_list_pluck( $this->strings, 'context' ) );
32 $this->selected_group = empty( $_GET['group'] ) || ! in_array( $_GET['group'], $this->groups ) ? -1 : $_GET['group'];
33
34 add_action( 'mlang_action_string-translation', array( &$this, 'save_translations' ) );
35 }
36
37 /**
38 * Displays the item information in a column ( default case )
39 *
40 * @since 0.6
41 *
42 * @param array $item
43 * @param string $column_name
44 * @return string
45 */
46 function column_default( $item, $column_name ) {
47 return $item[ $column_name ];
48 }
49
50 /**
51 * Displays the checkbox in first column
52 *
53 * @since 1.1
54 *
55 * @param array $item
56 * @return string
57 */
58 function column_cb( $item ) {
59 return sprintf(
60 '<label class="screen-reader-text" for="cb-select-%1$s">%2$s</label><input id="cb-select-%1$s" type="checkbox" name="strings[]" value="%1$s" %3$s />',
61 esc_attr( $item['row'] ),
62 /* translators: %s is a string potentially in any language */
63 sprintf( __( 'Select %s' ), format_to_edit( $item['string'] ) ),
64 empty( $item['icl'] ) ? 'disabled' : '' // only strings registered with WPML API can be removed
65 );
66 }
67
68 /**
69 * Displays the string to translate
70 *
71 * @since 1.0
72 *
73 * @param array $item
74 * @return string
75 */
76 function column_string( $item ) {
77 return format_to_edit( $item['string'] ); // don't interpret special chars for the string column
78 }
79
80 /**
81 * Displays the translations to edit
82 *
83 * @since 0.6
84 *
85 * @param array $item
86 * @return string
87 */
88 function column_translations( $item ) {
89 $languages = array_combine( wp_list_pluck( $this->languages, 'slug' ), wp_list_pluck( $this->languages, 'name' ) );
90 $out = '';
91
92 foreach ( $item['translations'] as $key => $translation ) {
93 $input_type = $item['multiline'] ?
94 '<textarea name="translation[%1$s][%2$s]" id="%1$s-%2$s">%4$s</textarea>' :
95 '<input type="text" name="translation[%1$s][%2$s]" id="%1$s-%2$s" value="%4$s" />';
96 $out .= sprintf( '<div class="translation"><label for="%1$s-%2$s">%3$s</label>'.$input_type.'</div>'."\n",
97 esc_attr( $key ),
98 esc_attr( $item['row'] ),
99 esc_html( $languages[ $key ] ),
100 format_to_edit( $translation ) ); // don't interpret special chars
101 }
102
103 return $out;
104 }
105
106 /**
107 * Gets the list of columns
108 *
109 * @since 0.6
110 *
111 * @return array the list of column titles
112 */
113 function get_columns() {
114 return array(
115 'cb' => '<input type="checkbox" />', // checkbox
116 'string' => __( 'String', 'polylang' ),
117 'name' => __( 'Name', 'polylang' ),
118 'context' => __( 'Group', 'polylang' ),
119 'translations' => __( 'Translations', 'polylang' ),
120 );
121 }
122
123 /**
124 * Gets the list of sortable columns
125 *
126 * @since 0.6
127 *
128 * @return array
129 */
130 function get_sortable_columns() {
131 return array(
132 'string' => array( 'string', false ),
133 'name' => array( 'name', false ),
134 'context' => array( 'context', false ),
135 );
136 }
137
138 /**
139 * Sort items
140 *
141 * @since 0.6
142 *
143 * @param object $a The first object to compare
144 * @param object $b The second object to compare
145 * @return int -1 or 1 if $a is considered to be respectively less than or greater than $b.
146 */
147 protected function usort_reorder( $a, $b ) {
148 $result = strcmp( $a[ $_GET['orderby'] ], $b[ $_GET['orderby'] ] ); // determine sort order
149 return ( empty( $_GET['order'] ) || 'asc' === $_GET['order'] ) ? $result : -$result; // send final sort direction to usort
150 }
151
152 /**
153 * Prepares the list of items for displaying
154 *
155 * @since 0.6
156 */
157 function prepare_items() {
158 $data = $this->strings;
159
160 // filter for search string
161 $s = empty( $_GET['s'] ) ? '' : wp_unslash( $_GET['s'] );
162 foreach ( $data as $key => $row ) {
163 if ( ( -1 !== $this->selected_group && $row['context'] !== $this->selected_group ) || ( ! empty( $s ) && stripos( $row['name'], $s ) === false && stripos( $row['string'], $s ) === false ) ) {
164 unset( $data[ $key ] );
165 }
166 }
167
168 // load translations
169 foreach ( $this->languages as $language ) {
170 // filters by language if requested
171 if ( ( $lg = get_user_meta( get_current_user_id(), 'pll_filter_content', true ) ) && $language->slug !== $lg ) {
172 continue;
173 }
174
175 $mo = new PLL_MO();
176 $mo->import_from_db( $language );
177 foreach ( $data as $key => $row ) {
178 $data[ $key ]['translations'][ $language->slug ] = $mo->translate( $row['string'] );
179 $data[ $key ]['row'] = $key; // store the row number for convenience
180 }
181 }
182
183 $per_page = $this->get_items_per_page( 'pll_strings_per_page' );
184 $this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
185
186 if ( ! empty( $_GET['orderby'] ) ) { // no sort by default
187 usort( $data, array( &$this, 'usort_reorder' ) );
188 }
189
190 $total_items = count( $data );
191 $this->items = array_slice( $data, ( $this->get_pagenum() - 1 ) * $per_page, $per_page );
192
193 $this->set_pagination_args( array(
194 'total_items' => $total_items,
195 'per_page' => $per_page,
196 'total_pages' => ceil( $total_items / $per_page ),
197 ) );
198 }
199
200 /**
201 * Get the list of possible bulk actions
202 *
203 * @since 1.1
204 *
205 * @return array
206 */
207 function get_bulk_actions() {
208 return array( 'delete' => __( 'Delete','polylang' ) );
209 }
210
211 /**
212 * Get the current action selected from the bulk actions dropdown.
213 * overrides parent function to avoid submit button to trigger bulk actions
214 *
215 * @since 1.8
216 *
217 * @return string|false The action name or False if no action was selected
218 */
219 public function current_action() {
220 return empty( $_POST['submit'] ) ? parent::current_action() : false;
221 }
222
223 /**
224 * Displays the dropdown list to filter strings per group
225 *
226 * @since 1.1
227 *
228 * @param string $which only 'top' is supported
229 */
230 function extra_tablenav( $which ) {
231 if ( 'top' !== $which ) {
232 return;
233 }
234
235 echo '<div class="alignleft actions">';
236 printf( '<label class="screen-reader-text" for="select-group" >%s</label>', __( 'Filter by group', 'polylang' ) );
237 echo '<select id="select-group" name="group">' . "\n";
238 printf(
239 '<option value="-1"%s>%s</option>' . "\n",
240 -1 === $this->group_selected ? ' selected="selected"' : '',
241 __( 'View all groups', 'polylang' )
242 );
243
244 foreach ( $this->groups as $group ) {
245 printf(
246 '<option value="%s"%s>%s</option>' . "\n",
247 esc_attr( urlencode( $group ) ),
248 $this->selected_group === $group ? ' selected="selected"' : '',
249 esc_html( $group )
250 );
251 }
252 echo '</select>'."\n";
253
254 submit_button( __( 'Filter' ), 'button', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
255 echo '</div>';
256 }
257
258 /**
259 * Saves the strings translations in DB
260 * Optionaly clean the DB
261 *
262 * @since 1.9
263 */
264 public function save_translations() {
265 check_admin_referer( 'string-translation', '_wpnonce_string-translation' );
266
267 if ( ! empty( $_POST['submit'] ) ) {
268 foreach ( $this->languages as $language ) {
269 if ( empty( $_POST['translation'][ $language->slug ] ) ) { // in case the language filter is active ( thanks to John P. Bloch )
270 continue;
271 }
272
273 $mo = new PLL_MO();
274 $mo->import_from_db( $language );
275
276 foreach ( $_POST['translation'][ $language->slug ] as $key => $translation ) {
277 /*
278 * Filter the string translation before it is saved in DB
279 * Allows to sanitize strings registered with pll_register_string
280 *
281 * @since 1.6
282 *
283 * @param string $translation the string translation
284 * @param string $name the name as defined in pll_register_string
285 * @param string $context the context as defined in pll_register_string
286 */
287 $translation = apply_filters( 'pll_sanitize_string_translation', $translation, $this->strings[ $key ]['name'], $this->strings[ $key ]['context'] );
288 $mo->add_entry( $mo->make_entry( $this->strings[ $key ]['string'], $translation ) );
289 }
290
291 // clean database ( removes all strings which were registered some day but are no more )
292 if ( ! empty( $_POST['clean'] ) ) {
293 $new_mo = new PLL_MO();
294
295 foreach ( $this->strings as $string ) {
296 $new_mo->add_entry( $mo->make_entry( $string['string'], $mo->translate( $string['string'] ) ) );
297 }
298 }
299
300 isset( $new_mo ) ? $new_mo->export_to_db( $language ) : $mo->export_to_db( $language );
301 }
302
303 add_settings_error( 'general', 'pll_strings_translations_updated', __( 'Translations updated.', 'polylang' ), 'updated' );
304
305 /**
306 * Fires after the strings translations are saved in DB
307 *
308 * @since 1.2
309 */
310 do_action( 'pll_save_strings_translations' );
311 }
312
313 // unregisters strings registered through WPML API
314 if ( $this->current_action() === 'delete' && ! empty( $_POST['strings'] ) && function_exists( 'icl_unregister_string' ) ) {
315 foreach ( $_POST['strings'] as $key ) {
316 icl_unregister_string( $this->strings[ $key ]['context'], $this->strings[ $key ]['name'] );
317 }
318 }
319
320 // to refresh the page ( possible thanks to the $_GET['noheader']=true )
321 $args = array_intersect_key( $_REQUEST, array_flip( array( 's', 'paged', 'group' ) ) );
322 if ( ! empty( $args['s'] ) ) {
323 $args['s'] = urlencode( $args['s'] ); // searched string needs to be encoded as it comes from $_POST
324 }
325 PLL_Settings::redirect( $args );
326 }
327 }
328