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/settings.php +133 -213 3.02.0.3 View file →
@@ -1,58 +1,46 @@
1 1 <?php
2 -/**
3 - * @package Polylang
4 - */
5 2
6 3 /**
7 - * A class for the Polylang settings pages, accessible from @see PLL().
4 + * A class for the Polylang settings pages
5 + * accessible in $polylang global object
8 6 *
7 + * properties:
8 + * options => inherited, reference to Polylang options array
9 + * model => inherited, reference to PLL_Model object
10 + * links_model => inherited, reference to PLL_Links_Model object
11 + * links => inherited, reference to PLL_Admin_Links object
12 + * static_pages => inherited, reference to PLL_Admin_Static_Pages object
13 + * filters_links => inherited, reference to PLL_Filters_Links object
14 + * curlang => inherited, optional, current language used to filter admin content
15 + * pref_lang => inherited, preferred language used as default when saving posts or terms
16 + *
9 17 * @since 1.2
10 18 */
11 19 class PLL_Settings extends PLL_Admin_Base {
20 + protected $active_tab, $modules;
12 21
13 22 /**
14 - * @var PLL_Admin_Model
15 - */
16 - public $model;
17 -
18 - /**
19 - * Name of the active module.
20 - *
21 - * @var string
22 - */
23 - protected $active_tab;
24 -
25 - /**
26 - * Array of modules classes.
27 - *
28 - * @var PLL_Settings_Module[]
29 - */
30 - protected $modules;
31 -
32 - /**
33 23 * Constructor
34 24 *
35 25 * @since 1.2
36 26 *
37 - * @param PLL_Links_Model $links_model Reference to the links model.
27 + * @param object $links_model
38 28 */
39 29 public function __construct( &$links_model ) {
40 30 parent::__construct( $links_model );
41 31
42 - if ( isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
43 - $this->active_tab = 'mlang' === $_GET['page'] ? 'lang' : substr( sanitize_key( $_GET['page'] ), 6 ); // phpcs:ignore WordPress.Security.NonceVerification
44 - }
32 + $this->active_tab = ! empty( $_GET['tab'] ) ? $_GET['tab'] : 'lang';
45 33
46 34 PLL_Admin_Strings::init();
47 35
36 + // FIXME put this as late as possible
48 37 add_action( 'admin_init', array( $this, 'register_settings_modules' ) );
49 38
50 - // Adds screen options and the about box in the languages admin panel
51 - add_action( 'load-toplevel_page_mlang', array( $this, 'load_page' ) );
52 - add_action( 'load-languages_page_mlang_strings', array( $this, 'load_page_strings' ) );
39 + // adds screen options and the about box in the languages admin panel
40 + add_action( 'load-settings_page_mlang', array( $this, 'load_page' ) );
53 41
54 - // Saves per-page value in screen option
42 + // saves per-page value in screen option
55 43 add_filter( 'set-screen-option', array( $this, 'set_screen_option' ), 10, 3 );
56 44 }
57 45
58 46 /**
@@ -58,25 +46,28 @@
58 46 /**
59 47 * Initializes the modules
60 48 *
61 49 * @since 1.8
62 - *
63 - * @return void
64 50 */
65 51 public function register_settings_modules() {
66 - $modules = array();
52 + $modules = array(
53 + 'PLL_Settings_Tools',
54 + 'PLL_Settings_Licenses',
55 + );
67 56
68 57 if ( $this->model->get_languages_list() ) {
69 - $modules = array(
58 + $modules = array_merge( array(
70 59 'PLL_Settings_Url',
71 60 'PLL_Settings_Browser',
72 61 'PLL_Settings_Media',
73 62 'PLL_Settings_CPT',
74 - );
63 + 'PLL_Settings_Sync',
64 + 'PLL_Settings_WPML',
65 + 'PLL_Settings_Share_Slug',
66 + 'PLL_Settings_Translate_Slugs',
67 + ), $modules );
75 68 }
76 69
77 - $modules[] = 'PLL_Settings_Licenses';
78 -
79 70 /**
80 71 * Filter the list of setting modules
81 72 *
82 73 * @since 1.8
@@ -91,16 +82,23 @@
91 82 }
92 83 }
93 84
94 85 /**
86 + * Adds the link to the languages panel in the WordPress admin menu
87 + *
88 + * @since 0.1
89 + */
90 + public function add_menus() {
91 + add_submenu_page( 'options-general.php', $title = __( 'Languages', 'polylang' ), $title, 'manage_options', 'mlang', array( $this, 'languages_page' ) );
92 + }
93 +
94 + /**
95 95 * Loads the about metabox
96 96 *
97 97 * @since 0.8
98 - *
99 - * @return void
100 98 */
101 99 public function metabox_about() {
102 - include __DIR__ . '/view-about.php';
100 + include( PLL_SETTINGS_INC.'/view-about.php' );
103 101 }
104 102
105 103 /**
106 104 * Adds screen options and the about box in the languages admin panel
@@ -105,50 +103,40 @@
105 103 /**
106 104 * Adds screen options and the about box in the languages admin panel
107 105 *
108 106 * @since 0.9.5
109 - *
110 - * @return void
111 107 */
112 108 public function load_page() {
113 - if ( ! defined( 'PLL_DISPLAY_ABOUT' ) || PLL_DISPLAY_ABOUT ) {
114 - add_meta_box(
115 - 'pll-about-box',
116 - __( 'About Polylang', 'polylang' ),
117 - array( $this, 'metabox_about' ),
118 - 'toplevel_page_mlang',
119 - 'normal'
120 - );
121 - }
109 + // test of $this->active_tab avoids displaying the automatically generated screen options on other tabs
110 + switch ( $this->active_tab ) {
111 + case 'lang':
112 + if ( ! defined( 'PLL_DISPLAY_ABOUT' ) || PLL_DISPLAY_ABOUT ) {
113 + add_meta_box(
114 + 'pll-about-box',
115 + __( 'About Polylang', 'polylang' ),
116 + array( $this, 'metabox_about' ),
117 + 'settings_page_mlang',
118 + 'normal'
119 + );
120 + }
122 121
123 - add_screen_option(
124 - 'per_page',
125 - array(
126 - 'label' => __( 'Languages', 'polylang' ),
127 - 'default' => 10,
128 - 'option' => 'pll_lang_per_page',
129 - )
130 - );
122 + add_screen_option( 'per_page', array(
123 + 'label' => __( 'Languages', 'polylang' ),
124 + 'default' => 10,
125 + 'option' => 'pll_lang_per_page',
126 + ) );
131 127
132 - add_action( 'admin_notices', array( $this, 'notice_objects_with_no_lang' ) );
133 - }
128 + add_action( 'admin_notices', array( $this, 'notice_objects_with_no_lang' ) );
129 + break;
134 130
135 - /**
136 - * Adds screen options in the strings translations admin panel
137 - *
138 - * @since 2.1
139 - *
140 - * @return void
141 - */
142 - public function load_page_strings() {
143 - add_screen_option(
144 - 'per_page',
145 - array(
146 - 'label' => __( 'Strings translations', 'polylang' ),
147 - 'default' => 10,
148 - 'option' => 'pll_strings_per_page',
149 - )
150 - );
131 + case 'strings':
132 + add_screen_option( 'per_page', array(
133 + 'label' => __( 'Strings translations', 'polylang' ),
134 + 'default' => 10,
135 + 'option' => 'pll_strings_per_page',
136 + ) );
137 + break;
138 + }
151 139 }
152 140
153 141 /**
154 142 * Save the "Views/Uploads per page" option set by this user
@@ -154,11 +142,11 @@
154 142 * Save the "Views/Uploads per page" option set by this user
155 143 *
156 144 * @since 0.9.5
157 145 *
158 - * @param mixed $status false or value returned by previous filter
159 - * @param string $option Name of the option being changed
160 - * @param string $value Value of the option
146 + * @param mixed $status false or value returned by previous filter
147 + * @param string $option Name of the option being changed
148 + * @param string $value Value of the option
161 149 *
162 150 * @return string New value if this is our option, otherwise nothing
163 151 */
164 152 public function set_screen_option( $status, $option, $value ) {
@@ -170,64 +158,44 @@
170 158 *
171 159 * @since 1.9
172 160 *
173 161 * @param string $action
174 - * @return void
175 162 */
176 163 public function handle_actions( $action ) {
177 164 switch ( $action ) {
178 165 case 'add':
179 166 check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
180 - $errors = $this->model->add_language( $_POST );
181 167
182 - if ( is_wp_error( $errors ) ) {
183 - foreach ( $errors->get_error_messages() as $message ) {
184 - add_settings_error( 'general', 'pll_add_language', $message );
168 + if ( $this->model->add_language( $_POST ) && 'en_US' !== $_POST['locale'] ) {
169 + // attempts to install the language pack
170 + require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
171 + if ( ! wp_download_language_pack( $_POST['locale'] ) ) {
172 + add_settings_error( 'general', 'pll_download_mo', __( 'The language was created, but the WordPress language file was not downloaded. Please install it manually.', 'polylang' ) );
185 173 }
186 - } else {
187 - add_settings_error( 'general', 'pll_languages_created', __( 'Language added.', 'polylang' ), 'updated' );
188 - $locale = sanitize_text_field( wp_unslash( $_POST['locale'] ) ); // phpcs:ignore WordPress.Security
189 174
190 - if ( 'en_US' !== $locale && current_user_can( 'install_languages' ) ) {
191 - // Attempts to install the language pack
192 - require_once ABSPATH . 'wp-admin/includes/translation-install.php';
193 - if ( ! wp_download_language_pack( $locale ) ) {
194 - add_settings_error( 'general', 'pll_download_mo', __( 'The language was created, but the WordPress language file was not downloaded. Please install it manually.', 'polylang' ) );
195 - }
196 -
197 - // Force checking for themes and plugins translations updates
198 - wp_clean_themes_cache();
199 - wp_clean_plugins_cache();
200 - }
175 + // force checking for themes and plugins translations updates
176 + wp_clean_themes_cache();
177 + wp_clean_plugins_cache();
201 178 }
202 - self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
203 - break;
179 + self::redirect(); // to refresh the page ( possible thanks to the $_GET['noheader']=true )
180 + break;
204 181
205 182 case 'delete':
206 183 check_admin_referer( 'delete-lang' );
207 184
208 - if ( ! empty( $_GET['lang'] ) && $this->model->delete_language( (int) $_GET['lang'] ) ) {
209 - add_settings_error( 'general', 'pll_languages_deleted', __( 'Language deleted.', 'polylang' ), 'updated' );
185 + if ( ! empty( $_GET['lang'] ) ) {
186 + $this->model->delete_language( (int) $_GET['lang'] );
210 187 }
211 188
212 - self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
213 - break;
189 + self::redirect(); // to refresh the page ( possible thanks to the $_GET['noheader']=true )
190 + break;
214 191
215 192 case 'update':
216 193 check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
217 - $errors = $this->model->update_language( $_POST );
194 + $error = $this->model->update_language( $_POST );
195 + self::redirect(); // to refresh the page ( possible thanks to the $_GET['noheader']=true )
196 + break;
218 197
219 - if ( is_wp_error( $errors ) ) {
220 - foreach ( $errors->get_error_messages() as $message ) {
221 - add_settings_error( 'general', 'pll_update_language', $message );
222 - }
223 - } else {
224 - add_settings_error( 'general', 'pll_languages_updated', __( 'Language updated.', 'polylang' ), 'updated' );
225 - }
226 -
227 - self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
228 - break;
229 -
230 198 case 'default-lang':
231 199 check_admin_referer( 'default-lang' );
232 200
233 201 if ( $lang = $this->model->get_language( (int) $_GET['lang'] ) ) {
@@ -233,10 +201,10 @@
233 201 if ( $lang = $this->model->get_language( (int) $_GET['lang'] ) ) {
234 202 $this->model->update_default_lang( $lang->slug );
235 203 }
236 204
237 - self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
238 - break;
205 + self::redirect(); // to refresh the page ( possible thanks to the $_GET['noheader']=true )
206 + break;
239 207
240 208 case 'content-default-lang':
241 209 check_admin_referer( 'content-default-lang' );
242 210
@@ -248,32 +216,22 @@
248 216 $this->model->set_language_in_mass( 'term', $nolang['terms'], $this->options['default_lang'] );
249 217 }
250 218 }
251 219
252 - self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
253 - break;
220 + self::redirect(); // to refresh the page ( possible thanks to the $_GET['noheader']=true )
221 + break;
254 222
255 223 case 'activate':
256 224 check_admin_referer( 'pll_activate' );
257 - if ( isset( $_GET['module'] ) ) {
258 - $module = sanitize_key( $_GET['module'] );
259 - if ( isset( $this->modules[ $module ] ) ) {
260 - $this->modules[ $module ]->activate();
261 - }
262 - }
225 + $this->modules[ $_GET['module'] ]->activate();
263 226 self::redirect();
264 - break;
227 + break;
265 228
266 229 case 'deactivate':
267 230 check_admin_referer( 'pll_deactivate' );
268 - if ( isset( $_GET['module'] ) ) {
269 - $module = sanitize_key( $_GET['module'] );
270 - if ( isset( $this->modules[ $module ] ) ) {
271 - $this->modules[ $module ]->deactivate();
272 - }
273 - }
231 + $this->modules[ $_GET['module'] ]->deactivate();
274 232 self::redirect();
275 - break;
233 + break;
276 234
277 235 default:
278 236 /**
279 237 * Fires when a non default action has been sent to Polylang settings
@@ -280,51 +238,65 @@
280 238 *
281 239 * @since 1.8
282 240 */
283 241 do_action( "mlang_action_$action" );
284 - break;
242 + break;
285 243 }
286 244 }
287 245
288 246 /**
289 247 * Displays the 3 tabs pages: languages, strings translations, settings
290 - * Also manages user input for these pages
248 + * also manages user input for these pages
291 249 *
292 250 * @since 0.1
293 - *
294 - * @return void
295 251 */
296 252 public function languages_page() {
253 + // prepare the list of tabs
254 + $tabs = array( 'lang' => __( 'Languages','polylang' ) );
255 +
256 + // only if at least one language has been created
257 + if ( $listlanguages = $this->model->get_languages_list() ) {
258 + $tabs['strings'] = __( 'Strings translations', 'polylang' );
259 + }
260 +
261 + $tabs['settings'] = __( 'Settings', 'polylang' );
262 +
263 + /**
264 + * Filter the list of tabs in Polylang settings
265 + *
266 + * @since 1.5.1
267 + *
268 + * @param array $tabs list of tab names
269 + */
270 + $tabs = apply_filters( 'pll_settings_tabs', $tabs );
271 +
297 272 switch ( $this->active_tab ) {
298 273 case 'lang':
299 - // Prepare the list table of languages
274 + // prepare the list table of languages
300 275 $list_table = new PLL_Table_Languages();
301 - $list_table->prepare_items( $this->model->get_languages_list() );
302 - break;
276 + $list_table->prepare_items( $listlanguages );
277 + break;
303 278
304 279 case 'strings':
305 - $string_table = new PLL_Table_String( $this->model->get_languages_list() );
280 + $string_table = new PLL_Table_String( $listlanguages );
306 281 $string_table->prepare_items();
307 - break;
282 + break;
308 283 }
309 284
310 - // Handle user input
311 - $action = isset( $_REQUEST['pll_action'] ) ? sanitize_key( $_REQUEST['pll_action'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
312 - if ( 'edit' === $action && ! empty( $_GET['lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
313 - // phpcs:ignore WordPress.Security.NonceVerification, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
285 + // handle user input
286 + $action = isset( $_REQUEST['pll_action'] ) ? $_REQUEST['pll_action'] : '';
287 + if ( 'edit' === $action && ! empty( $_GET['lang'] ) ) {
314 288 $edit_lang = $this->model->get_language( (int) $_GET['lang'] );
315 289 } else {
316 290 $this->handle_actions( $action );
317 291 }
318 292
319 - // Displays the page
320 - include __DIR__ . '/view-languages.php';
293 + // displays the page
294 + include( PLL_SETTINGS_INC.'/view-languages.php' );
321 295 }
322 296
323 297 /**
324 298 * Enqueues scripts and styles
325 - *
326 - * @return void
327 299 */
328 300 public function admin_enqueue_scripts() {
329 301 parent::admin_enqueue_scripts();
330 302
@@ -329,12 +301,12 @@
329 301 parent::admin_enqueue_scripts();
330 302
331 303 $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
332 304
333 - wp_enqueue_script( 'pll_admin', plugins_url( '/js/build/admin' . $suffix . '.js', POLYLANG_BASENAME ), array( 'jquery', 'wp-ajax-response', 'postbox', 'jquery-ui-selectmenu' ), POLYLANG_VERSION, true );
334 - wp_localize_script( 'pll_admin', 'pll_admin', array( 'dismiss_notice' => esc_html__( 'Dismiss this notice.', 'polylang' ) ) );
305 + wp_enqueue_script( 'pll_admin', POLYLANG_URL .'/js/admin'.$suffix.'.js', array( 'jquery', 'wp-ajax-response', 'postbox', 'jquery-ui-selectmenu' ), POLYLANG_VERSION );
306 + wp_localize_script( 'pll_admin', 'pll_flag_base_url', POLYLANG_URL . '/flags/' );
335 307
336 - wp_enqueue_style( 'pll_selectmenu', plugins_url( '/css/build/selectmenu' . $suffix . '.css', POLYLANG_BASENAME ), array(), POLYLANG_VERSION );
308 + wp_enqueue_style( 'pll_selectmenu', POLYLANG_URL .'/css/selectmenu'.$suffix.'.css', array(), POLYLANG_VERSION );
337 309 }
338 310
339 311 /**
340 312 * Displays a notice when there are objects with no language assigned
@@ -339,17 +311,15 @@
339 311 /**
340 312 * Displays a notice when there are objects with no language assigned
341 313 *
342 314 * @since 1.8
343 - *
344 - * @return void
345 315 */
346 316 public function notice_objects_with_no_lang() {
347 - if ( ! empty( $this->options['default_lang'] ) && $this->model->get_objects_with_no_lang( 1 ) ) {
317 + if ( ! empty( $this->options['default_lang'] ) && $this->model->get_objects_with_no_lang() ) {
348 318 printf(
349 319 '<div class="error"><p>%s <a href="%s">%s</a></p></div>',
350 320 esc_html__( 'There are posts, pages, categories or tags without language.', 'polylang' ),
351 - esc_url( wp_nonce_url( '?page=mlang&pll_action=content-default-lang&noheader=true', 'content-default-lang' ) ),
321 + wp_nonce_url( '?page=mlang&amp;pll_action=content-default-lang&amp;noheader=true', 'content-default-lang' ),
352 322 esc_html__( 'You can set them all to the default language.', 'polylang' )
353 323 );
354 324 }
355 325 }
@@ -360,65 +330,15 @@
360 330 *
361 331 * @since 1.5
362 332 *
363 333 * @param array $args query arguments to add to the url
364 - * @return void
365 334 */
366 - public static function redirect( $args = array() ) {
335 + static public function redirect( $args = array() ) {
367 336 if ( $errors = get_settings_errors() ) {
368 337 set_transient( 'settings_errors', $errors, 30 );
369 338 $args['settings-updated'] = 1;
370 339 }
371 - // Remove possible 'pll_action' and 'lang' query args from the referer before redirecting
372 - wp_safe_redirect( add_query_arg( $args, remove_query_arg( array( 'pll_action', 'lang' ), wp_get_referer() ) ) );
340 + // remove possible 'pll_action' and 'lang' query args from the referer before redirecting
341 + wp_safe_redirect( add_query_arg( $args, remove_query_arg( array( 'pll_action', 'lang' ), wp_get_referer() ) ) );
373 342 exit;
374 - }
375 -
376 - /**
377 - * Get the list of predefined languages
378 - *
379 - * @since 2.3
380 - *
381 - * @return string[] {
382 - * @type string $code ISO 639-1 language code.
383 - * @type string $locale WordPress locale.
384 - * @type string $name Native language name.
385 - * @type string $dir Text direction: 'ltr' or 'rtl'.
386 - * @type string $flag Flag code, generally the country code.
387 - * @type string $w3c W3C locale.
388 - * @type string $facebook Facebook locale.
389 - * }
390 - */
391 - public static function get_predefined_languages() {
392 - require_once ABSPATH . 'wp-admin/includes/translation-install.php';
393 -
394 - $languages = include __DIR__ . '/languages.php';
395 - $translations = wp_get_available_translations();
396 -
397 - // Keep only languages with existing WP language pack
398 - // Unless the transient has expired and we don't have an internet connection to refresh it
399 - if ( ! empty( $translations ) ) {
400 - $translations['en_US'] = ''; // Languages packs don't include en_US
401 - $languages = array_intersect_key( $languages, $translations );
402 - }
403 -
404 - /**
405 - * Filter the list of predefined languages
406 - *
407 - * @since 1.7.10
408 - * @since 2.3 The languages arrays use associative keys instead of numerical keys
409 - * @see https://github.com/polylang/polylang/blob/2.8.2/settings/languages.php the list of predefined languages
410 - *
411 - * @param array $languages
412 - */
413 - $languages = apply_filters( 'pll_predefined_languages', $languages );
414 -
415 - // Keep only languages with all necessary informations
416 - foreach ( $languages as $k => $lang ) {
417 - if ( ! isset( $lang['code'], $lang['locale'], $lang['name'], $lang['dir'], $lang['flag'] ) ) {
418 - unset( $languages[ $k ] );
419 - }
420 - }
421 -
422 - return $languages;
423 343 }
424 344 }