PluginProbe
Polylang / 2.0.3
Polylang v2.0.3
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 | settings/table-string.php +67 -177 3.0.32.0.3 View file →
@@ -1,11 +1,8 @@
1 1 <?php
2 -/**
3 - * @package Polylang
4 - */
5 2
6 3 if ( ! class_exists( 'WP_List_Table' ) ) {
7 - require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; // since WP 3.1
4 + require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); // since WP 3.1
8 5 }
9 6
10 7 /**
11 8 * A class to create the strings translations table
@@ -13,64 +10,28 @@
13 10 *
14 11 * @since 0.6
15 12 */
16 13 class PLL_Table_String extends WP_List_Table {
17 - /**
18 - * The list of languages.
19 - *
20 - * @var PLL_Language[]
21 - */
22 - protected $languages;
14 + protected $languages, $strings, $groups, $selected_group;
23 15
24 16 /**
25 - * Registered strings.
17 + * Constructor
26 18 *
27 - * @var array
28 - */
29 - protected $strings;
30 -
31 - /**
32 - * The string groups.
33 - *
34 - * @var string[]
35 - */
36 - protected $groups;
37 -
38 - /**
39 - * The selected string group or -1 if none is selected.
40 - *
41 - * @var string|int
42 - */
43 - protected $selected_group;
44 -
45 - /**
46 - * Constructor.
47 - *
48 19 * @since 0.6
49 20 *
50 - * @param PLL_Language[] $languages List of languages.
21 + * @param array $languages list of languages
51 22 */
52 - public function __construct( $languages ) {
53 - parent::__construct(
54 - array(
55 - 'plural' => 'Strings translations', // Do not translate ( used for css class )
56 - 'ajax' => false,
57 - )
58 - );
23 + function __construct( $languages ) {
24 + parent::__construct( array(
25 + 'plural' => 'Strings translations', // Do not translate ( used for css class )
26 + 'ajax' => false,
27 + ) );
59 28
60 29 $this->languages = $languages;
61 30 $this->strings = PLL_Admin_Strings::get_strings();
62 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'];
63 33
64 - $this->selected_group = -1;
65 -
66 - if ( ! empty( $_GET['group'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
67 - $group = sanitize_text_field( wp_unslash( $_GET['group'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
68 - if ( in_array( $group, $this->groups ) ) {
69 - $this->selected_group = $group;
70 - }
71 - }
72 -
73 34 add_action( 'mlang_action_string-translation', array( $this, 'save_translations' ) );
74 35 }
75 36
76 37 /**
@@ -81,9 +42,9 @@
81 42 * @param array $item
82 43 * @param string $column_name
83 44 * @return string
84 45 */
85 - public function column_default( $item, $column_name ) {
46 + function column_default( $item, $column_name ) {
86 47 return $item[ $column_name ];
87 48 }
88 49
89 50 /**
@@ -93,14 +54,14 @@
93 54 *
94 55 * @param array $item
95 56 * @return string
96 57 */
97 - public function column_cb( $item ) {
58 + function column_cb( $item ) {
98 59 return sprintf(
99 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 />',
100 61 esc_attr( $item['row'] ),
101 62 /* translators: accessibility text, %s is a string potentially in any language */
102 - sprintf( __( 'Select %s', 'polylang' ), format_to_edit( $item['string'] ) ),
63 + sprintf( __( 'Select %s' ), format_to_edit( $item['string'] ) ),
103 64 empty( $item['icl'] ) ? 'disabled' : '' // Only strings registered with WPML API can be removed
104 65 );
105 66 }
106 67
@@ -111,9 +72,9 @@
111 72 *
112 73 * @param array $item
113 74 * @return string
114 75 */
115 - public function column_string( $item ) {
76 + function column_string( $item ) {
116 77 return format_to_edit( $item['string'] ); // Don't interpret special chars for the string column
117 78 }
118 79
119 80 /**
@@ -123,9 +84,9 @@
123 84 *
124 85 * @param array $item
125 86 * @return string
126 87 */
127 - public function column_translations( $item ) {
88 + function column_translations( $item ) {
128 89 $languages = array_combine( wp_list_pluck( $this->languages, 'slug' ), wp_list_pluck( $this->languages, 'name' ) );
129 90 $out = '';
130 91
131 92 foreach ( $item['translations'] as $key => $translation ) {
@@ -131,15 +92,13 @@
131 92 foreach ( $item['translations'] as $key => $translation ) {
132 93 $input_type = $item['multiline'] ?
133 94 '<textarea name="translation[%1$s][%2$s]" id="%1$s-%2$s">%4$s</textarea>' :
134 95 '<input type="text" name="translation[%1$s][%2$s]" id="%1$s-%2$s" value="%4$s" />';
135 - $out .= sprintf(
136 - '<div class="translation"><label for="%1$s-%2$s">%3$s</label>' . $input_type . '</div>' . "\n",
96 + $out .= sprintf( '<div class="translation"><label for="%1$s-%2$s">%3$s</label>'.$input_type.'</div>'."\n",
137 97 esc_attr( $key ),
138 98 esc_attr( $item['row'] ),
139 99 esc_html( $languages[ $key ] ),
140 - format_to_edit( $translation ) // Don't interpret special chars
141 - );
100 + format_to_edit( $translation ) ); // Don't interpret special chars
142 101 }
143 102
144 103 return $out;
145 104 }
@@ -144,17 +103,17 @@
144 103 return $out;
145 104 }
146 105
147 106 /**
148 - * Gets the list of columns.
107 + * Gets the list of columns
149 108 *
150 109 * @since 0.6
151 110 *
152 - * @return string[] The list of column titles.
111 + * @return array the list of column titles
153 112 */
154 - public function get_columns() {
113 + function get_columns() {
155 114 return array(
156 - 'cb' => '<input type="checkbox" />', // Checkbox.
115 + 'cb' => '<input type="checkbox" />', // Checkbox
157 116 'string' => esc_html__( 'String', 'polylang' ),
158 117 'name' => esc_html__( 'Name', 'polylang' ),
159 118 'context' => esc_html__( 'Group', 'polylang' ),
160 119 'translations' => esc_html__( 'Translations', 'polylang' ),
@@ -167,9 +126,9 @@
167 126 * @since 0.6
168 127 *
169 128 * @return array
170 129 */
171 - public function get_sortable_columns() {
130 + function get_sortable_columns() {
172 131 return array(
173 132 'string' => array( 'string', false ),
174 133 'name' => array( 'name', false ),
175 134 'context' => array( 'context', false ),
@@ -176,42 +135,8 @@
176 135 );
177 136 }
178 137
179 138 /**
180 - * Gets the name of the default primary column.
181 - *
182 - * @since 2.1
183 - *
184 - * @return string Name of the default primary column, in this case, 'string'.
185 - */
186 - protected function get_default_primary_column_name() {
187 - return 'string';
188 - }
189 -
190 - /**
191 - * Search for a string in translations. Case insensitive.
192 - *
193 - * @since 2.6
194 - *
195 - * @param PLL_MO[] $mos An array of PLL_MO objects.
196 - * @param string $s Searched string.
197 - * @return string[] Found strings.
198 - */
199 - protected function search_in_translations( $mos, $s ) {
200 - $founds = array();
201 -
202 - foreach ( $mos as $mo ) {
203 - foreach ( wp_list_pluck( $mo->entries, 'translations' ) as $string => $translation ) {
204 - if ( false !== stripos( $translation[0], $s ) ) {
205 - $founds[] = $string;
206 - }
207 - }
208 - }
209 -
210 - return array_unique( $founds );
211 - }
212 -
213 - /**
214 139 * Sort items
215 140 *
216 141 * @since 0.6
217 142 *
@@ -219,17 +144,10 @@
219 144 * @param object $b The second object to compare
220 145 * @return int -1 or 1 if $a is considered to be respectively less than or greater than $b.
221 146 */
222 147 protected function usort_reorder( $a, $b ) {
223 - if ( ! empty( $_GET['orderby'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
224 - $orderby = sanitize_key( $_GET['orderby'] ); // phpcs:ignore WordPress.Security.NonceVerification
225 - if ( isset( $a[ $orderby ], $b[ $orderby ] ) ) {
226 - $result = strcmp( $a[ $orderby ], $b[ $orderby ] ); // Determine sort order
227 - return ( empty( $_GET['order'] ) || 'asc' === $_GET['order'] ) ? $result : -$result; // phpcs:ignore WordPress.Security.NonceVerification
228 - }
229 - }
230 -
231 - return 0;
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
232 150 }
233 151
234 152 /**
235 153 * Prepares the list of items for displaying
@@ -234,84 +152,61 @@
234 152 /**
235 153 * Prepares the list of items for displaying
236 154 *
237 155 * @since 0.6
238 - *
239 - * @return void
240 156 */
241 - public function prepare_items() {
242 - // Is admin language filter active?
243 - if ( $lg = get_user_meta( get_current_user_id(), 'pll_filter_content', true ) ) {
244 - $languages = wp_list_filter( $this->languages, array( 'slug' => $lg ) );
245 - } else {
246 - $languages = $this->languages;
247 - }
248 -
249 - // Load translations
250 - $mo = array();
251 - foreach ( $languages as $language ) {
252 - $mo[ $language->slug ] = new PLL_MO();
253 - $mo[ $language->slug ]->import_from_db( $language );
254 - }
255 -
157 + function prepare_items() {
256 158 $data = $this->strings;
257 159
258 - // Filter by selected group
259 - if ( -1 !== $this->selected_group ) {
260 - $data = wp_list_filter( $data, array( 'context' => $this->selected_group ) );
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 + }
261 166 }
262 167
263 - // Filter by searched string
264 - $s = empty( $_GET['s'] ) ? '' : wp_unslash( $_GET['s'] ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
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 + }
265 174
266 - if ( ! empty( $s ) ) {
267 - // Search in translations
268 - $in_translations = $this->search_in_translations( $mo, $s );
269 -
175 + $mo = new PLL_MO();
176 + $mo->import_from_db( $language );
270 177 foreach ( $data as $key => $row ) {
271 - if ( stripos( $row['name'], $s ) === false && stripos( $row['string'], $s ) === false && ! in_array( $row['string'], $in_translations ) ) {
272 - unset( $data[ $key ] );
273 - }
178 + $data[ $key ]['translations'][ $language->slug ] = $mo->translate( $row['string'] );
179 + $data[ $key ]['row'] = $key; // Store the row number for convenience
274 180 }
275 181 }
276 182
277 - // Sorting
278 - uasort( $data, array( $this, 'usort_reorder' ) );
279 -
280 - // Paging
281 183 $per_page = $this->get_items_per_page( 'pll_strings_per_page' );
282 184 $this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
283 185
186 + if ( ! empty( $_GET['orderby'] ) ) { // No sort by default
187 + usort( $data, array( $this, 'usort_reorder' ) );
188 + }
189 +
284 190 $total_items = count( $data );
285 - $this->items = array_slice( $data, ( $this->get_pagenum() - 1 ) * $per_page, $per_page, true );
191 + $this->items = array_slice( $data, ( $this->get_pagenum() - 1 ) * $per_page, $per_page );
286 192
287 - $this->set_pagination_args(
288 - array(
289 - 'total_items' => $total_items,
290 - 'per_page' => $per_page,
291 - 'total_pages' => ceil( $total_items / $per_page ),
292 - )
293 - );
294 -
295 - // Translate strings
296 - // Kept for the end as it is a slow process
297 - foreach ( $languages as $language ) {
298 - foreach ( $this->items as $key => $row ) {
299 - $this->items[ $key ]['translations'][ $language->slug ] = $mo[ $language->slug ]->translate( $row['string'] );
300 - $this->items[ $key ]['row'] = $key; // Store the row number for convenience
301 - }
302 - }
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 + ) );
303 198 }
304 199
305 200 /**
306 - * Get the list of possible bulk actions.
201 + * Get the list of possible bulk actions
307 202 *
308 203 * @since 1.1
309 204 *
310 - * @return string[] Array of bulk actions.
205 + * @return array
311 206 */
312 - public function get_bulk_actions() {
313 - return array( 'delete' => __( 'Delete', 'polylang' ) );
207 + function get_bulk_actions() {
208 + return array( 'delete' => __( 'Delete','polylang' ) );
314 209 }
315 210
316 211 /**
317 212 * Get the current action selected from the bulk actions dropdown.
@@ -321,9 +216,9 @@
321 216 *
322 217 * @return string|false The action name or False if no action was selected
323 218 */
324 219 public function current_action() {
325 - return empty( $_POST['submit'] ) ? parent::current_action() : false; // phpcs:ignore WordPress.Security.NonceVerification
220 + return empty( $_POST['submit'] ) ? parent::current_action() : false;
326 221 }
327 222
328 223 /**
329 224 * Displays the dropdown list to filter strings per group
@@ -330,11 +225,10 @@
330 225 *
331 226 * @since 1.1
332 227 *
333 228 * @param string $which only 'top' is supported
334 - * @return void
335 229 */
336 - public function extra_tablenav( $which ) {
230 + function extra_tablenav( $which ) {
337 231 if ( 'top' !== $which ) {
338 232 return;
339 233 }
340 234
@@ -346,9 +240,9 @@
346 240 );
347 241 echo '<select id="select-group" name="group">' . "\n";
348 242 printf(
349 243 '<option value="-1"%s>%s</option>' . "\n",
350 - selected( $this->selected_group, -1, false ),
244 + -1 === $this->group_selected ? ' selected="selected"' : '',
351 245 esc_html__( 'View all groups', 'polylang' )
352 246 );
353 247
354 248 foreach ( $this->groups as $group ) {
@@ -354,15 +248,15 @@
354 248 foreach ( $this->groups as $group ) {
355 249 printf(
356 250 '<option value="%s"%s>%s</option>' . "\n",
357 251 esc_attr( urlencode( $group ) ),
358 - selected( $this->selected_group, $group, false ),
252 + $this->selected_group === $group ? ' selected="selected"' : '',
359 253 esc_html( $group )
360 254 );
361 255 }
362 - echo '</select>' . "\n";
256 + echo '</select>'."\n";
363 257
364 - submit_button( __( 'Filter', 'polylang' ), 'button', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
258 + submit_button( __( 'Filter' ), 'button', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
365 259 echo '</div>';
366 260 }
367 261
368 262 /**
@@ -369,10 +263,8 @@
369 263 * Saves the strings translations in DB
370 264 * Optionaly clean the DB
371 265 *
372 266 * @since 1.9
373 - *
374 - * @return void
375 267 */
376 268 public function save_translations() {
377 269 check_admin_referer( 'string-translation', '_wpnonce_string-translation' );
378 270
@@ -377,9 +269,9 @@
377 269 check_admin_referer( 'string-translation', '_wpnonce_string-translation' );
378 270
379 271 if ( ! empty( $_POST['submit'] ) ) {
380 272 foreach ( $this->languages as $language ) {
381 - if ( empty( $_POST['translation'][ $language->slug ] ) || ! is_array( $_POST['translation'][ $language->slug ] ) ) { // In case the language filter is active ( thanks to John P. Bloch )
273 + if ( empty( $_POST['translation'][ $language->slug ] ) ) { // In case the language filter is active ( thanks to John P. Bloch )
382 274 continue;
383 275 }
384 276
385 277 $mo = new PLL_MO();
@@ -384,20 +276,18 @@
384 276
385 277 $mo = new PLL_MO();
386 278 $mo->import_from_db( $language );
387 279
388 - $translations = array_map( 'trim', wp_unslash( $_POST['translation'][ $language->slug ] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
389 - foreach ( $translations as $key => $translation ) {
280 + foreach ( $_POST['translation'][ $language->slug ] as $key => $translation ) {
390 281 /**
391 282 * Filter the string translation before it is saved in DB
392 283 * Allows to sanitize strings registered with pll_register_string
393 284 *
394 285 * @since 1.6
395 - * @since 2.7 The translation passed to the filter is unslashed.
396 286 *
397 - * @param string $translation The string translation.
398 - * @param string $name The name as defined in pll_register_string.
399 - * @param string $context The context as defined in pll_register_string.
287 + * @param string $translation the string translation
288 + * @param string $name the name as defined in pll_register_string
289 + * @param string $context the context as defined in pll_register_string
400 290 */
401 291 $translation = apply_filters( 'pll_sanitize_string_translation', $translation, $this->strings[ $key ]['name'], $this->strings[ $key ]['context'] );
402 292 $mo->add_entry( $mo->make_entry( $this->strings[ $key ]['string'], $translation ) );
403 293 }
@@ -425,9 +315,9 @@
425 315 }
426 316
427 317 // Unregisters strings registered through WPML API
428 318 if ( $this->current_action() === 'delete' && ! empty( $_POST['strings'] ) && function_exists( 'icl_unregister_string' ) ) {
429 - foreach ( array_map( 'sanitize_key', $_POST['strings'] ) as $key ) {
319 + foreach ( $_POST['strings'] as $key ) {
430 320 icl_unregister_string( $this->strings[ $key ]['context'], $this->strings[ $key ]['name'] );
431 321 }
432 322 }
433 323