PluginProbe
Polylang / 3.7.1
Polylang v3.7.1
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 / settings.php

settings.php in Polylang 3.7.1, at settings/settings.php

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