PluginProbe
Polylang / 2.8
Polylang v2.8
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 2.8, at settings/settings.php

405 lines 12.1 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
8 * accessible in $polylang global object
9 *
10 * Properties:
11 * options => inherited, reference to Polylang options array
12 * model => inherited, reference to PLL_Model object
13 * links_model => inherited, reference to PLL_Links_Model object
14 * links => inherited, reference to PLL_Admin_Links object
15 * static_pages => inherited, reference to PLL_Admin_Static_Pages object
16 * filters_links => inherited, reference to PLL_Filters_Links object
17 * curlang => inherited, optional, current language used to filter admin content
18 * pref_lang => inherited, preferred language used as default when saving posts or terms
19 *
20 * @since 1.2
21 */
22 class PLL_Settings extends PLL_Admin_Base {
23
24 /**
25 * Name of the active module
26 *
27 * @var string $active_tab
28 */
29 protected $active_tab;
30
31 /**
32 * Array of modules classes
33 *
34 * @var array $modules
35 */
36 protected $modules;
37
38 /**
39 * Constructor
40 *
41 * @since 1.2
42 *
43 * @param object $links_model
44 */
45 public function __construct( &$links_model ) {
46 parent::__construct( $links_model );
47
48 if ( isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
49 $this->active_tab = 'mlang' === $_GET['page'] ? 'lang' : substr( sanitize_key( $_GET['page'] ), 6 ); // phpcs:ignore WordPress.Security.NonceVerification
50 }
51
52 PLL_Admin_Strings::init();
53
54 add_action( 'admin_init', array( $this, 'register_settings_modules' ) );
55
56 // Adds screen options and the about box in the languages admin panel
57 add_action( 'load-toplevel_page_mlang', array( $this, 'load_page' ) );
58 add_action( 'load-languages_page_mlang_strings', array( $this, 'load_page_strings' ) );
59
60 // Saves per-page value in screen option
61 add_filter( 'set-screen-option', array( $this, 'set_screen_option' ), 10, 3 );
62 }
63
64 /**
65 * Initializes the modules
66 *
67 * @since 1.8
68 */
69 public function register_settings_modules() {
70 $modules = array();
71
72 if ( $this->model->get_languages_list() ) {
73 $modules = array(
74 'PLL_Settings_Url',
75 'PLL_Settings_Browser',
76 'PLL_Settings_Media',
77 'PLL_Settings_CPT',
78 );
79 }
80
81 $modules[] = 'PLL_Settings_Licenses';
82
83 /**
84 * Filter the list of setting modules
85 *
86 * @since 1.8
87 *
88 * @param array $modules the list of module classes
89 */
90 $modules = apply_filters( 'pll_settings_modules', $modules );
91
92 foreach ( $modules as $key => $class ) {
93 $key = is_numeric( $key ) ? strtolower( str_replace( 'PLL_Settings_', '', $class ) ) : $key;
94 $this->modules[ $key ] = new $class( $this );
95 }
96 }
97
98 /**
99 * Loads the about metabox
100 *
101 * @since 0.8
102 */
103 public function metabox_about() {
104 include __DIR__ . '/view-about.php';
105 }
106
107 /**
108 * Adds screen options and the about box in the languages admin panel
109 *
110 * @since 0.9.5
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 public function load_page_strings() {
141 add_screen_option(
142 'per_page',
143 array(
144 'label' => __( 'Strings translations', 'polylang' ),
145 'default' => 10,
146 'option' => 'pll_strings_per_page',
147 )
148 );
149 }
150
151 /**
152 * Save the "Views/Uploads per page" option set by this user
153 *
154 * @since 0.9.5
155 *
156 * @param mixed $status false or value returned by previous filter
157 * @param string $option Name of the option being changed
158 * @param string $value Value of the option
159 *
160 * @return string New value if this is our option, otherwise nothing
161 */
162 public function set_screen_option( $status, $option, $value ) {
163 return 'pll_lang_per_page' === $option || 'pll_strings_per_page' === $option ? $value : $status;
164 }
165
166 /**
167 * Manages the user input for the languages pages
168 *
169 * @since 1.9
170 *
171 * @param string $action
172 */
173 public function handle_actions( $action ) {
174 switch ( $action ) {
175 case 'add':
176 check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
177 $errors = $this->model->add_language( $_POST );
178
179 if ( is_wp_error( $errors ) ) {
180 foreach ( $errors->get_error_messages() as $message ) {
181 add_settings_error( 'general', 'pll_add_language', $message );
182 }
183 } else {
184 add_settings_error( 'general', 'pll_languages_created', __( 'Language added.', 'polylang' ), 'updated' );
185 $locale = sanitize_text_field( wp_unslash( $_POST['locale'] ) ); // phpcs:ignore WordPress.Security
186
187 if ( 'en_US' !== $locale ) {
188 // Attempts to install the language pack
189 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
190 if ( ! wp_download_language_pack( $locale ) ) {
191 add_settings_error( 'general', 'pll_download_mo', __( 'The language was created, but the WordPress language file was not downloaded. Please install it manually.', 'polylang' ) );
192 }
193
194 // Force checking for themes and plugins translations updates
195 wp_clean_themes_cache();
196 wp_clean_plugins_cache();
197 }
198 }
199 self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
200 break;
201
202 case 'delete':
203 check_admin_referer( 'delete-lang' );
204
205 if ( ! empty( $_GET['lang'] ) && $this->model->delete_language( (int) $_GET['lang'] ) ) {
206 add_settings_error( 'general', 'pll_languages_deleted', __( 'Language deleted.', 'polylang' ), 'updated' );
207 }
208
209 self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
210 break;
211
212 case 'update':
213 check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
214 $errors = $this->model->update_language( $_POST );
215
216 if ( is_wp_error( $errors ) ) {
217 foreach ( $errors->get_error_messages() as $message ) {
218 add_settings_error( 'general', 'pll_update_language', $message );
219 }
220 } else {
221 add_settings_error( 'general', 'pll_languages_updated', __( 'Language updated.', 'polylang' ), 'updated' );
222 }
223
224 self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
225 break;
226
227 case 'default-lang':
228 check_admin_referer( 'default-lang' );
229
230 if ( $lang = $this->model->get_language( (int) $_GET['lang'] ) ) {
231 $this->model->update_default_lang( $lang->slug );
232 }
233
234 self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
235 break;
236
237 case 'content-default-lang':
238 check_admin_referer( 'content-default-lang' );
239
240 if ( $nolang = $this->model->get_objects_with_no_lang() ) {
241 if ( ! empty( $nolang['posts'] ) ) {
242 $this->model->set_language_in_mass( 'post', $nolang['posts'], $this->options['default_lang'] );
243 }
244 if ( ! empty( $nolang['terms'] ) ) {
245 $this->model->set_language_in_mass( 'term', $nolang['terms'], $this->options['default_lang'] );
246 }
247 }
248
249 self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
250 break;
251
252 case 'activate':
253 check_admin_referer( 'pll_activate' );
254 if ( isset( $_GET['module'] ) ) {
255 $module = sanitize_key( $_GET['module'] );
256 if ( isset( $this->modules[ $module ] ) ) {
257 $this->modules[ $module ]->activate();
258 }
259 }
260 self::redirect();
261 break;
262
263 case 'deactivate':
264 check_admin_referer( 'pll_deactivate' );
265 if ( isset( $_GET['module'] ) ) {
266 $module = sanitize_key( $_GET['module'] );
267 if ( isset( $this->modules[ $module ] ) ) {
268 $this->modules[ $module ]->deactivate();
269 }
270 }
271 self::redirect();
272 break;
273
274 default:
275 /**
276 * Fires when a non default action has been sent to Polylang settings
277 *
278 * @since 1.8
279 */
280 do_action( "mlang_action_$action" );
281 break;
282 }
283 }
284
285 /**
286 * Displays the 3 tabs pages: languages, strings translations, settings
287 * Also manages user input for these pages
288 *
289 * @since 0.1
290 */
291 public function languages_page() {
292 switch ( $this->active_tab ) {
293 case 'lang':
294 // Prepare the list table of languages
295 $list_table = new PLL_Table_Languages();
296 $list_table->prepare_items( $this->model->get_languages_list() );
297 break;
298
299 case 'strings':
300 $string_table = new PLL_Table_String( $this->model->get_languages_list() );
301 $string_table->prepare_items();
302 break;
303 }
304
305 // Handle user input
306 $action = isset( $_REQUEST['pll_action'] ) ? sanitize_key( $_REQUEST['pll_action'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
307 if ( 'edit' === $action && ! empty( $_GET['lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
308 // phpcs:ignore WordPress.Security.NonceVerification, WordPressVIPMinimum.Variables.VariableAnalysis.UnusedVariable
309 $edit_lang = $this->model->get_language( (int) $_GET['lang'] );
310 } else {
311 $this->handle_actions( $action );
312 }
313
314 // Displays the page
315 include __DIR__ . '/view-languages.php';
316 }
317
318 /**
319 * Enqueues scripts and styles
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/admin' . $suffix . '.js', POLYLANG_FILE ), array( 'jquery', 'wp-ajax-response', 'postbox', 'jquery-ui-selectmenu' ), POLYLANG_VERSION );
327 wp_localize_script( 'pll_admin', 'pll_flag_base_url', plugins_url( '/flags/', POLYLANG_FILE ) );
328
329 wp_enqueue_style( 'pll_selectmenu', plugins_url( '/css/selectmenu' . $suffix . '.css', POLYLANG_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 public function notice_objects_with_no_lang() {
338 if ( ! empty( $this->options['default_lang'] ) && $this->model->get_objects_with_no_lang( 1 ) ) {
339 printf(
340 '<div class="error"><p>%s <a href="%s">%s</a></p></div>',
341 esc_html__( 'There are posts, pages, categories or tags without language.', 'polylang' ),
342 esc_url( wp_nonce_url( '?page=mlang&pll_action=content-default-lang&noheader=true', 'content-default-lang' ) ),
343 esc_html__( 'You can set them all to the default language.', 'polylang' )
344 );
345 }
346 }
347
348 /**
349 * Redirects to language page ( current active tab )
350 * saves error messages in a transient for reuse in redirected page
351 *
352 * @since 1.5
353 *
354 * @param array $args query arguments to add to the url
355 */
356 public static function redirect( $args = array() ) {
357 if ( $errors = get_settings_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 public static function get_predefined_languages() {
372 require_once ABSPATH . 'wp-admin/includes/translation-install.php';
373
374 $languages = include __DIR__ . '/languages.php';
375 $translations = wp_get_available_translations();
376
377 // Keep only languages with existing WP language pack
378 // Unless the transient has expired and we don't have an internet connection to refresh it
379 if ( ! empty( $translations ) ) {
380 $translations['en_US'] = ''; // Languages packs don't include en_US
381 $languages = array_intersect_key( $languages, $translations );
382 }
383
384 /**
385 * Filter the list of predefined languages
386 *
387 * @since 1.7.10
388 * @since 2.3 The languages arrays use associative keys instead of numerical keys
389 * @see settings/languages.php
390 *
391 * @param array $languages
392 */
393 $languages = apply_filters( 'pll_predefined_languages', $languages );
394
395 // Keep only languages with all necessary informations
396 foreach ( $languages as $k => $lang ) {
397 if ( ! isset( $lang['code'], $lang['locale'], $lang['name'], $lang['dir'], $lang['flag'] ) ) {
398 unset( $languages[ $k ] );
399 }
400 }
401
402 return $languages;
403 }
404 }
405