PluginProbe
Polylang / 3.4.2
Polylang v3.4.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 / settings / settings.php

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

419 lines 12.0 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 per-page value in screen option
55 add_filter( 'set-screen-option', array( $this, 'set_screen_option' ), 10, 3 );
56 }
57
58 /**
59 * Initializes the modules
60 *
61 * @since 1.8
62 *
63 * @return void
64 */
65 public function register_settings_modules() {
66 $modules = array();
67
68 if ( $this->model->has_languages() ) {
69 $modules = array(
70 'PLL_Settings_Url',
71 'PLL_Settings_Browser',
72 'PLL_Settings_Media',
73 'PLL_Settings_CPT',
74 );
75 }
76
77 $modules[] = 'PLL_Settings_Licenses';
78
79 /**
80 * Filter the list of setting modules
81 *
82 * @since 1.8
83 *
84 * @param array $modules the list of module classes
85 */
86 $modules = apply_filters( 'pll_settings_modules', $modules );
87
88 foreach ( $modules as $key => $class ) {
89 $key = is_numeric( $key ) ? strtolower( str_replace( 'PLL_Settings_', '', $class ) ) : $key;
90 $this->modules[ $key ] = new $class( $this );
91 }
92 }
93
94 /**
95 * Loads the about metabox
96 *
97 * @since 0.8
98 *
99 * @return void
100 */
101 public function metabox_about() {
102 include __DIR__ . '/view-about.php';
103 }
104
105 /**
106 * Adds screen options and the about box in the languages admin panel
107 *
108 * @since 0.9.5
109 *
110 * @return void
111 */
112 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 }
122
123 add_screen_option(
124 'per_page',
125 array(
126 'label' => __( 'Languages', 'polylang' ),
127 'default' => 10,
128 'option' => 'pll_lang_per_page',
129 )
130 );
131
132 add_action( 'admin_notices', array( $this, 'notice_objects_with_no_lang' ) );
133 }
134
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 );
151 }
152
153 /**
154 * Save the "Views/Uploads per page" option set by this user
155 *
156 * @since 0.9.5
157 *
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
161 *
162 * @return string New value if this is our option, otherwise nothing
163 */
164 public function set_screen_option( $status, $option, $value ) {
165 return 'pll_lang_per_page' === $option || 'pll_strings_per_page' === $option ? $value : $status;
166 }
167
168 /**
169 * Manages the user input for the languages pages
170 *
171 * @since 1.9
172 *
173 * @param string $action
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 foreach ( $errors->get_error_messages() as $message ) {
184 add_settings_error( 'general', 'pll_add_language', $message );
185 }
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
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 }
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 add_settings_error( 'general', 'pll_languages_deleted', __( 'Language deleted.', 'polylang' ), 'updated' );
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 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 case 'default-lang':
231 check_admin_referer( 'default-lang' );
232
233 if ( $lang = $this->model->get_language( (int) $_GET['lang'] ) ) {
234 $this->model->update_default_lang( $lang->slug );
235 }
236
237 self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
238 break;
239
240 case 'content-default-lang':
241 check_admin_referer( 'content-default-lang' );
242
243 $this->model->set_language_in_mass();
244
245 self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
246 break;
247
248 case 'activate':
249 check_admin_referer( 'pll_activate' );
250 if ( isset( $_GET['module'] ) ) {
251 $module = sanitize_key( $_GET['module'] );
252 if ( isset( $this->modules[ $module ] ) ) {
253 $this->modules[ $module ]->activate();
254 }
255 }
256 self::redirect();
257 break;
258
259 case 'deactivate':
260 check_admin_referer( 'pll_deactivate' );
261 if ( isset( $_GET['module'] ) ) {
262 $module = sanitize_key( $_GET['module'] );
263 if ( isset( $this->modules[ $module ] ) ) {
264 $this->modules[ $module ]->deactivate();
265 }
266 }
267 self::redirect();
268 break;
269
270 default:
271 /**
272 * Fires when a non default action has been sent to Polylang settings
273 *
274 * @since 1.8
275 */
276 do_action( "mlang_action_$action" );
277 break;
278 }
279 }
280
281 /**
282 * Displays the 3 tabs pages: languages, strings translations, settings
283 * Also manages user input for these pages
284 *
285 * @since 0.1
286 *
287 * @return void
288 */
289 public function languages_page() {
290 switch ( $this->active_tab ) {
291 case 'lang':
292 // Prepare the list table of languages
293 $list_table = new PLL_Table_Languages();
294 $list_table->prepare_items( $this->model->get_languages_list() );
295 break;
296
297 case 'strings':
298 $string_table = new PLL_Table_String( $this->model->get_languages_list() );
299 $string_table->prepare_items();
300 break;
301 }
302
303 // Handle user input
304 $action = isset( $_REQUEST['pll_action'] ) ? sanitize_key( $_REQUEST['pll_action'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
305 if ( 'edit' === $action && ! empty( $_GET['lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
306 // phpcs:ignore WordPress.Security.NonceVerification, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
307 $edit_lang = $this->model->get_language( (int) $_GET['lang'] );
308 } else {
309 $this->handle_actions( $action );
310 }
311
312 // Displays the page
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_admin', plugins_url( '/js/build/admin' . $suffix . '.js', POLYLANG_ROOT_FILE ), array( 'jquery', 'wp-ajax-response', 'postbox', 'jquery-ui-selectmenu' ), POLYLANG_VERSION, true );
327 wp_localize_script( 'pll_admin', 'pll_admin', 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();
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 * @type string $code ISO 639-1 language code.
377 * @type string $locale WordPress locale.
378 * @type string $name Native language name.
379 * @type string $dir Text direction: 'ltr' or 'rtl'.
380 * @type string $flag Flag code, generally the country code.
381 * @type string $w3c W3C locale.
382 * @type string $facebook Facebook locale.
383 * }
384 */
385 public static function get_predefined_languages() {
386 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
387
388 $languages = include __DIR__ . '/languages.php';
389 $translations = wp_get_available_translations();
390
391 // Keep only languages with existing WP language pack
392 // Unless the transient has expired and we don't have an internet connection to refresh it
393 if ( ! empty( $translations ) ) {
394 $translations['en_US'] = ''; // Languages packs don't include en_US
395 $languages = array_intersect_key( $languages, $translations );
396 }
397
398 /**
399 * Filter the list of predefined languages
400 *
401 * @since 1.7.10
402 * @since 2.3 The languages arrays use associative keys instead of numerical keys
403 * @see https://github.com/polylang/polylang/blob/2.8.2/settings/languages.php the list of predefined languages
404 *
405 * @param array $languages
406 */
407 $languages = apply_filters( 'pll_predefined_languages', $languages );
408
409 // Keep only languages with all necessary informations
410 foreach ( $languages as $k => $lang ) {
411 if ( ! isset( $lang['code'], $lang['locale'], $lang['name'], $lang['dir'], $lang['flag'] ) ) {
412 unset( $languages[ $k ] );
413 }
414 }
415
416 return $languages;
417 }
418 }
419