PluginProbe
Polylang / 3.2.2
Polylang v3.2.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.2.2, at settings/settings.php

426 lines 12.3 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
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 * 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->get_languages_list() ) {
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 if ( $nolang = $this->model->get_objects_with_no_lang() ) {
244 if ( ! empty( $nolang['posts'] ) ) {
245 $this->model->set_language_in_mass( 'post', $nolang['posts'], $this->options['default_lang'] );
246 }
247 if ( ! empty( $nolang['terms'] ) ) {
248 $this->model->set_language_in_mass( 'term', $nolang['terms'], $this->options['default_lang'] );
249 }
250 }
251
252 self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
253 break;
254
255 case 'activate':
256 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 }
263 self::redirect();
264 break;
265
266 case 'deactivate':
267 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 }
274 self::redirect();
275 break;
276
277 default:
278 /**
279 * Fires when a non default action has been sent to Polylang settings
280 *
281 * @since 1.8
282 */
283 do_action( "mlang_action_$action" );
284 break;
285 }
286 }
287
288 /**
289 * Displays the 3 tabs pages: languages, strings translations, settings
290 * Also manages user input for these pages
291 *
292 * @since 0.1
293 *
294 * @return void
295 */
296 public function languages_page() {
297 switch ( $this->active_tab ) {
298 case 'lang':
299 // Prepare the list table of languages
300 $list_table = new PLL_Table_Languages();
301 $list_table->prepare_items( $this->model->get_languages_list() );
302 break;
303
304 case 'strings':
305 $string_table = new PLL_Table_String( $this->model->get_languages_list() );
306 $string_table->prepare_items();
307 break;
308 }
309
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
314 $edit_lang = $this->model->get_language( (int) $_GET['lang'] );
315 } else {
316 $this->handle_actions( $action );
317 }
318
319 // Displays the page
320 include __DIR__ . '/view-languages.php';
321 }
322
323 /**
324 * Enqueues scripts and styles
325 *
326 * @return void
327 */
328 public function admin_enqueue_scripts() {
329 parent::admin_enqueue_scripts();
330
331 $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
332
333 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 );
334 wp_localize_script( 'pll_admin', 'pll_admin', array( 'dismiss_notice' => esc_html__( 'Dismiss this notice.', 'polylang' ) ) );
335
336 wp_enqueue_style( 'pll_selectmenu', plugins_url( '/css/build/selectmenu' . $suffix . '.css', POLYLANG_ROOT_FILE ), array(), POLYLANG_VERSION );
337 }
338
339 /**
340 * Displays a notice when there are objects with no language assigned
341 *
342 * @since 1.8
343 *
344 * @return void
345 */
346 public function notice_objects_with_no_lang() {
347 if ( ! empty( $this->options['default_lang'] ) && $this->model->get_objects_with_no_lang( 1 ) ) {
348 printf(
349 '<div class="error"><p>%s <a href="%s">%s</a></p></div>',
350 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' ) ),
352 esc_html__( 'You can set them all to the default language.', 'polylang' )
353 );
354 }
355 }
356
357 /**
358 * Redirects to language page ( current active tab )
359 * saves error messages in a transient for reuse in redirected page
360 *
361 * @since 1.5
362 *
363 * @param array $args query arguments to add to the url
364 * @return void
365 */
366 public static function redirect( $args = array() ) {
367 $errors = get_settings_errors();
368 if ( ! empty( $errors ) ) {
369 set_transient( 'settings_errors', $errors, 30 );
370 $args['settings-updated'] = 1;
371 }
372 // Remove possible 'pll_action' and 'lang' query args from the referer before redirecting
373 wp_safe_redirect( add_query_arg( $args, remove_query_arg( array( 'pll_action', 'lang' ), wp_get_referer() ) ) );
374 exit;
375 }
376
377 /**
378 * Get the list of predefined languages
379 *
380 * @since 2.3
381 *
382 * @return string[] {
383 * @type string $code ISO 639-1 language code.
384 * @type string $locale WordPress locale.
385 * @type string $name Native language name.
386 * @type string $dir Text direction: 'ltr' or 'rtl'.
387 * @type string $flag Flag code, generally the country code.
388 * @type string $w3c W3C locale.
389 * @type string $facebook Facebook locale.
390 * }
391 */
392 public static function get_predefined_languages() {
393 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
394
395 $languages = include __DIR__ . '/languages.php';
396 $translations = wp_get_available_translations();
397
398 // Keep only languages with existing WP language pack
399 // Unless the transient has expired and we don't have an internet connection to refresh it
400 if ( ! empty( $translations ) ) {
401 $translations['en_US'] = ''; // Languages packs don't include en_US
402 $languages = array_intersect_key( $languages, $translations );
403 }
404
405 /**
406 * Filter the list of predefined languages
407 *
408 * @since 1.7.10
409 * @since 2.3 The languages arrays use associative keys instead of numerical keys
410 * @see https://github.com/polylang/polylang/blob/2.8.2/settings/languages.php the list of predefined languages
411 *
412 * @param array $languages
413 */
414 $languages = apply_filters( 'pll_predefined_languages', $languages );
415
416 // Keep only languages with all necessary informations
417 foreach ( $languages as $k => $lang ) {
418 if ( ! isset( $lang['code'], $lang['locale'], $lang['name'], $lang['dir'], $lang['flag'] ) ) {
419 unset( $languages[ $k ] );
420 }
421 }
422
423 return $languages;
424 }
425 }
426