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

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