PluginProbe
Polylang / 3.6.7
Polylang v3.6.7
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.6.7, at settings/settings.php

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