PluginProbe
Polylang / 2.6.2
Polylang v2.6.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 / admin / admin-filters.php

admin-filters.php in Polylang 2.6.2, at admin/admin-filters.php

268 lines 9.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Setup miscellaneous admin filters as well as filters common to admin and frontend
5 *
6 * @since 1.2
7 */
8 class PLL_Admin_Filters extends PLL_Filters {
9
10 /**
11 * Constructor: setups filters and actions
12 *
13 * @since 1.2
14 *
15 * @param object $polylang
16 */
17 public function __construct( &$polylang ) {
18 parent::__construct( $polylang );
19
20 // Widgets languages filter
21 add_action( 'in_widget_form', array( $this, 'in_widget_form' ), 10, 3 );
22 add_filter( 'widget_update_callback', array( $this, 'widget_update_callback' ), 10, 4 );
23
24 // Language management for users
25 add_action( 'personal_options_update', array( $this, 'personal_options_update' ) );
26 add_action( 'edit_user_profile_update', array( $this, 'personal_options_update' ) );
27 add_action( 'personal_options', array( $this, 'personal_options' ) );
28
29 // Upgrades languages files after a core upgrade ( timing is important )
30 // Backward compatibility WP < 4.0 *AND* Polylang < 1.6
31 add_action( '_core_updated_successfully', array( $this, 'upgrade_languages' ), 1 ); // since WP 3.3
32
33 // Upgrades plugins and themes translations files
34 add_filter( 'themes_update_check_locales', array( $this, 'update_check_locales' ) );
35 add_filter( 'plugins_update_check_locales', array( $this, 'update_check_locales' ) );
36
37 // We need specific filters for German and Danish
38 $specific_locales = array( 'da_DK', 'de_DE', 'de_DE_formal', 'de_CH', 'de_CH_informal', 'ca', 'sr_RS', 'bs_BA' );
39 if ( array_intersect( $this->model->get_languages_list( array( 'fields' => 'locale' ) ), $specific_locales ) ) {
40 add_filter( 'sanitize_title', array( $this, 'sanitize_title' ), 10, 3 );
41 add_filter( 'sanitize_user', array( $this, 'sanitize_user' ), 10, 3 );
42 }
43
44 add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
45 }
46
47 /**
48 * Modifies the widgets forms to add our language dropdown list
49 *
50 * @since 0.3
51 *
52 * @param object $widget Widget instance
53 * @param null $return Not used
54 * @param array $instance Widget settings
55 */
56 public function in_widget_form( $widget, $return, $instance ) {
57 $screen = get_current_screen();
58
59 // Test the Widgets screen and the Customizer to avoid displaying the option in page builders
60 // Saving the widget reloads the form. And curiously the action is in $_REQUEST but neither in $_POST, nor in $_GET.
61 if ( ( isset( $screen ) && 'widgets' === $screen->base ) || ( isset( $_REQUEST['action'] ) && 'save-widget' === $_REQUEST['action'] ) || isset( $GLOBALS['wp_customize'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
62 $dropdown = new PLL_Walker_Dropdown();
63
64 $dropdown_html = $dropdown->walk(
65 array_merge(
66 array( (object) array( 'slug' => 0, 'name' => __( 'All languages', 'polylang' ) ) ),
67 $this->model->get_languages_list()
68 ),
69 array(
70 'name' => $widget->id . '_lang_choice',
71 'class' => 'tags-input pll-lang-choice',
72 'selected' => empty( $instance['pll_lang'] ) ? '' : $instance['pll_lang'],
73 )
74 );
75
76 printf(
77 '<p><label for="%1$s">%2$s %3$s</label></p>',
78 esc_attr( $widget->id . '_lang_choice' ),
79 esc_html__( 'The widget is displayed for:', 'polylang' ),
80 $dropdown_html // phpcs:ignore WordPress.Security.EscapeOutput
81 );
82 }
83 }
84
85 /**
86 * Called when widget options are saved
87 * saves the language associated to the widget
88 *
89 * @since 0.3
90 *
91 * @param array $instance Widget options
92 * @param array $new_instance Not used
93 * @param array $old_instance Not used
94 * @param object $widget WP_Widget object
95 * @return array Widget options
96 */
97 public function widget_update_callback( $instance, $new_instance, $old_instance, $widget ) {
98 $key = $widget->id . '_lang_choice';
99
100 if ( ! empty( $_POST[ $key ] ) && $lang = $this->model->get_language( sanitize_key( $_POST[ $key ] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
101 $instance['pll_lang'] = $lang->slug;
102 } else {
103 unset( $instance['pll_lang'] );
104 }
105
106 return $instance;
107 }
108
109 /**
110 * Updates language user preference set in user profile
111 *
112 * @since 0.4
113 *
114 * @param int $user_id
115 */
116 public function personal_options_update( $user_id ) {
117 // Biography translations
118 foreach ( $this->model->get_languages_list() as $lang ) {
119 $meta = $lang->slug == $this->options['default_lang'] ? 'description' : 'description_' . $lang->slug;
120 $description = empty( $_POST[ 'description_' . $lang->slug ] ) ? '' : trim( $_POST[ 'description_' . $lang->slug ] ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
121
122 /** This filter is documented in wp-includes/user.php */
123 $description = apply_filters( 'pre_user_description', $description ); // Applies WP default filter wp_filter_kses
124 update_user_meta( $user_id, $meta, $description );
125 }
126 }
127
128 /**
129 * Outputs hidden information to modify the biography form with js
130 *
131 * @since 0.4
132 *
133 * @param object $profileuser
134 */
135 public function personal_options( $profileuser ) {
136 foreach ( $this->model->get_languages_list() as $lang ) {
137 $meta = $lang->slug == $this->options['default_lang'] ? 'description' : 'description_' . $lang->slug;
138
139 /** This filter is documented in wp-includes/user.php */
140 $description = apply_filters( 'user_description', get_user_meta( $profileuser->ID, $meta, true ) ); // Applies WP default filter wp_kses_data
141
142 printf(
143 '<input type="hidden" class="biography" name="%s___%s" value="%s" />',
144 esc_attr( $lang->slug ),
145 esc_attr( $lang->name ),
146 esc_attr( $description )
147 );
148 }
149 }
150
151 /**
152 * Upgrades languages files after a core upgrade
153 * only for backward compatibility WP < 4.0 *AND* Polylang < 1.6
154 *
155 * @since 0.6
156 *
157 * @param string $version new WP version
158 */
159 public function upgrade_languages( $version ) {
160 // $GLOBALS['wp_version'] is the old WP version
161 if ( version_compare( $version, '4.0', '>=' ) && version_compare( $GLOBALS['wp_version'], '4.0', '<' ) ) {
162
163 /** This filter is documented in wp-admin/includes/update-core.php */
164 apply_filters( 'update_feedback', __( 'Upgrading language files&#8230;', 'polylang' ) );
165 PLL_Upgrade::download_language_packs();
166 }
167 }
168
169 /**
170 * Allows to update translations files for plugins and themes
171 *
172 * @since 1.6
173 *
174 * @param array $locales Not used
175 * @return array list of locales to update
176 */
177 public function update_check_locales( $locales ) {
178 return $this->model->get_languages_list( array( 'fields' => 'locale' ) );
179 }
180
181 /**
182 * Filters the locale according to the current language instead of the language
183 * of the admin interface
184 *
185 * @since 2.0
186 *
187 * @param string $locale
188 * @return string
189 */
190 public function get_locale( $locale ) {
191 if ( isset( $_POST['post_lang_choice'] ) && $lang = $this->model->get_language( sanitize_key( $_POST['post_lang_choice'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
192 $locale = $lang->locale;
193 } elseif ( isset( $_POST['term_lang_choice'] ) && $lang = $this->model->get_language( sanitize_key( $_POST['term_lang_choice'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
194 $locale = $lang->locale;
195 } elseif ( isset( $_POST['inline_lang_choice'] ) && $lang = $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
196 $locale = $lang->locale;
197 } elseif ( ! empty( $this->curlang ) ) {
198 $locale = $this->curlang->locale;
199 }
200
201 return $locale;
202 }
203
204 /**
205 * Maybe fix the result of sanitize_title() in case the languages include German or Danish
206 * Without this filter, if language of the title being sanitized is different from the language
207 * used for the admin interface and if one this language is German or Danish, some specific
208 * characters such as ä, ö, ü, ß are incorrectly sanitized.
209 *
210 * @since 2.0
211 *
212 * @param string $title Sanitized title.
213 * @param string $raw_title The title prior to sanitization.
214 * @param string $context The context for which the title is being sanitized.
215 * @return string
216 */
217 public function sanitize_title( $title, $raw_title, $context ) {
218 static $once = false;
219
220 if ( ! $once && 'save' == $context && ! empty( $title ) ) {
221 $once = true;
222 add_filter( 'locale', array( $this, 'get_locale' ), 20 ); // After the filter for the admin interface
223 $title = sanitize_title( $raw_title, '', $context );
224 remove_filter( 'locale', array( $this, 'get_locale' ), 20 );
225 $once = false;
226 }
227 return $title;
228 }
229
230 /**
231 * Maybe fix the result of sanitize_user() in case the languages include German or Danish
232 *
233 * @since 2.0
234 *
235 * @param string $username Sanitized username.
236 * @param string $raw_username The username prior to sanitization.
237 * @param bool $strict Whether to limit the sanitization to specific characters. Default false.
238 * @return string
239 */
240 public function sanitize_user( $username, $raw_username, $strict ) {
241 static $once = false;
242
243 if ( ! $once ) {
244 $once = true;
245 add_filter( 'locale', array( $this, 'get_locale' ), 20 ); // After the filter for the admin interface
246 $username = sanitize_user( $raw_username, '', $strict );
247 remove_filter( 'locale', array( $this, 'get_locale' ), 20 );
248 $once = false;
249 }
250 return $username;
251 }
252
253 /**
254 * Adds a text direction dependent class to the body
255 *
256 * @since 2.2
257 *
258 * @param string $classes Space-separated list of CSS classes.
259 * @return string
260 */
261 public function admin_body_class( $classes ) {
262 if ( ! empty( $this->curlang ) ) {
263 $classes .= ' pll-dir-' . ( $this->curlang->is_rtl ? 'rtl' : 'ltr' );
264 }
265 return $classes;
266 }
267 }
268