PluginProbe
Polylang / 2.7.3
Polylang v2.7.3
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
← All changes | admin/admin-base.php +103 -126 3.0.22.7.3 View file →
@@ -1,66 +1,28 @@
1 1 <?php
2 -/**
3 - * @package Polylang
4 - */
5 2
6 3 /**
7 - * Setup features available on all admin pages.
4 + * Base class for both admin
8 5 *
9 6 * @since 1.8
10 7 */
11 -abstract class PLL_Admin_Base extends PLL_Base {
12 - /**
13 - * Current language (used to filter the content).
14 - *
15 - * @var PLL_Language
16 - */
17 - public $curlang;
8 +class PLL_Admin_Base extends PLL_Base {
9 + public $filter_lang, $curlang, $pref_lang;
18 10
19 11 /**
20 - * Language selected in the admin language filter.
12 + * Loads the polylang text domain
13 + * Setups actions needed on all admin pages
21 14 *
22 - * @var PLL_Language
23 - */
24 - public $filter_lang;
25 -
26 - /**
27 - * Preferred language to assign to new contents.
28 - *
29 - * @var PLL_Language
30 - */
31 - public $pref_lang;
32 -
33 - /**
34 - * @var PLL_Filters_Links
35 - */
36 - public $filters_links;
37 -
38 - /**
39 - * @var PLL_Admin_Links
40 - */
41 - public $links;
42 -
43 - /**
44 - * @var PLL_Admin_Notices
45 - */
46 - public $notices;
47 -
48 - /**
49 - * @var PLL_Admin_Static_Pages
50 - */
51 - public $static_pages;
52 -
53 - /**
54 - * Setups actions needed on all admin pages.
55 - *
56 15 * @since 1.8
57 16 *
58 - * @param PLL_Links_Model $links_model Reference to the links model.
17 + * @param object $links_model
59 18 */
60 19 public function __construct( &$links_model ) {
61 20 parent::__construct( $links_model );
62 21
22 + // Plugin i18n, only needed for backend
23 + load_plugin_textdomain( 'polylang', false, basename( POLYLANG_DIR ) . '/languages' );
24 +
63 25 // Adds the link to the languages panel in the WordPress admin menu
64 26 add_action( 'admin_menu', array( $this, 'add_menus' ) );
65 27
66 28 // Setup js scripts and css styles
@@ -67,8 +29,15 @@
67 29 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
68 30 add_action( 'admin_print_footer_scripts', array( $this, 'admin_print_footer_scripts' ), 0 ); // High priority in case an ajax request is sent by an immediately invoked function
69 31
70 32 add_action( 'customize_controls_enqueue_scripts', array( $this, 'customize_controls_enqueue_scripts' ) );
33 +
34 + if ( defined( 'POLYLANG_PRO' ) ) {
35 + new PLL_Pro();
36 + } elseif ( ! defined( 'PLL_LINGOTEK_AD' ) || PLL_LINGOTEK_AD ) {
37 + require_once POLYLANG_DIR . '/lingotek/lingotek.php'; // Lingotek
38 + add_action( 'wp_loaded', array( new PLL_Lingotek(), 'init' ) );
39 + }
71 40 }
72 41
73 42 /**
74 43 * Setups filters and action needed on all admin pages and on plugins page
@@ -80,8 +49,16 @@
80 49 parent::init();
81 50
82 51 $this->notices = new PLL_Admin_Notices( $this );
83 52
53 + if ( Polylang::is_wizard() && class_exists( 'PLL_Wizard_Pro' ) ) {
54 + // Instantiate PLL_Wizard_Pro class after all PLL_Admin object is all initialized.
55 + // After PLL_Admin::maybe_load_sync_post which is hooked on admin_init with priority 20.
56 + add_action( 'admin_init', array( $this, 'instantiate_wizard_pro' ), 30 );
57 + }
58 +
59 + $this->wizard = new PLL_Wizard( $this );
60 +
84 61 if ( ! $this->model->get_languages_list() ) {
85 62 return;
86 63 }
87 64
@@ -95,8 +72,14 @@
95 72 add_filter( 'request', array( $this, 'request' ) );
96 73
97 74 // Adds the languages in admin bar
98 75 add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 100 ); // 100 determines the position
76 +
77 + // Translate slugs, only for pretty permalinks
78 + if ( get_option( 'permalink_structure' ) && class_exists( 'PLL_Translate_Slugs' ) ) {
79 + $slugs_model = new PLL_Translate_Slugs_Model( $this );
80 + $this->translate_slugs = new PLL_Translate_Slugs( $slugs_model, $this->curlang );
81 + }
99 82 }
100 83
101 84 /**
102 85 * Adds the link to the languages panel in the WordPress admin menu
@@ -101,10 +84,8 @@
101 84 /**
102 85 * Adds the link to the languages panel in the WordPress admin menu
103 86 *
104 87 * @since 0.1
105 - *
106 - * @return void
107 88 */
108 89 public function add_menus() {
109 90 global $admin_page_hooks;
110 91
@@ -132,9 +113,9 @@
132 113 foreach ( $tabs as $tab => $title ) {
133 114 $page = 'lang' === $tab ? 'mlang' : "mlang_$tab";
134 115 if ( empty( $parent ) ) {
135 116 $parent = $page;
136 - add_menu_page( $title, __( 'Languages', 'polylang' ), 'manage_options', $page, '__return_null', 'dashicons-translation' );
117 + add_menu_page( $title, __( 'Languages', 'polylang' ), 'manage_options', $page, null, 'dashicons-translation' );
137 118 $admin_page_hooks[ $page ] = 'languages'; // Hack to avoid the localization of the hook name. See: https://core.trac.wordpress.org/ticket/18857
138 119 }
139 120
140 121 add_submenu_page( $parent, $title, $title, 'manage_options', $page, array( $this, 'languages_page' ) );
@@ -144,10 +125,8 @@
144 125 /**
145 126 * Setup js scripts & css styles ( only on the relevant pages )
146 127 *
147 128 * @since 0.6
148 - *
149 - * @return void
150 129 */
151 130 public function admin_enqueue_scripts() {
152 131 $screen = get_current_screen();
153 132 if ( empty( $screen ) ) {
@@ -172,14 +151,14 @@
172 151 $scripts['post'] = array( array( 'edit', 'upload' ), array( 'jquery', 'wp-ajax-response' ), 0, 1 );
173 152
174 153 // Classic editor.
175 154 if ( ! method_exists( $screen, 'is_block_editor' ) || ! $screen->is_block_editor() ) {
176 - $scripts['classic-editor'] = array( array( 'post', 'media', 'async-upload' ), array( 'jquery', 'wp-ajax-response', 'post', 'jquery-ui-dialog', 'wp-i18n' ), 0, 1 );
155 + $scripts['classic-editor'] = array( array( 'post', 'media', 'async-upload' ), array( 'jquery', 'wp-ajax-response', 'post' ), 0, 1 );
177 156 }
178 157
179 158 // Block editor with legacy metabox in WP 5.0+.
180 159 if ( method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() && ! pll_use_block_editor_plugin() ) {
181 - $scripts['block-editor'] = array( array( 'post' ), array( 'jquery', 'wp-ajax-response', 'wp-api-fetch', 'jquery-ui-dialog', 'wp-i18n' ), 0, 1 );
160 + $scripts['block-editor'] = array( array( 'post' ), array( 'jquery', 'wp-ajax-response', 'wp-api-fetch' ), 0, 1 );
182 161 }
183 162 }
184 163
185 164 if ( ! empty( $screen->taxonomy ) && $this->model->is_translated_taxonomy( $screen->taxonomy ) ) {
@@ -187,17 +166,13 @@
187 166 }
188 167
189 168 foreach ( $scripts as $script => $v ) {
190 169 if ( in_array( $screen->base, $v[0] ) && ( $v[2] || $this->model->get_languages_list() ) ) {
191 - wp_enqueue_script( 'pll_' . $script, plugins_url( '/js/build/' . $script . $suffix . '.js', POLYLANG_ROOT_FILE ), $v[1], POLYLANG_VERSION, $v[3] );
192 - if ( 'classic-editor' === $script || 'block-editor' === $script ) {
193 - wp_set_script_translations( 'pll_' . $script, 'polylang' );
194 - }
170 + wp_enqueue_script( 'pll_' . $script, plugins_url( '/js/' . $script . $suffix . '.js', POLYLANG_FILE ), $v[1], POLYLANG_VERSION, $v[3] );
195 171 }
196 172 }
197 173
198 - wp_register_style( 'polylang_admin', plugins_url( '/css/build/admin' . $suffix . '.css', POLYLANG_ROOT_FILE ), array( 'wp-jquery-ui-dialog' ), POLYLANG_VERSION );
199 - wp_enqueue_style( 'polylang_dialog', plugins_url( '/css/build/dialog' . $suffix . '.css', POLYLANG_ROOT_FILE ), array( 'polylang_admin' ), POLYLANG_VERSION );
174 + wp_enqueue_style( 'polylang_admin', plugins_url( '/css/admin' . $suffix . '.css', POLYLANG_FILE ), array(), POLYLANG_VERSION );
200 175
201 176 $this->localize_scripts();
202 177 }
203 178
@@ -204,15 +179,13 @@
204 179 /**
205 180 * Enqueue scripts to the WP Customizer.
206 181 *
207 182 * @since 2.4.0
208 - *
209 - * @return void
210 183 */
211 184 public function customize_controls_enqueue_scripts() {
212 185 if ( $this->model->get_languages_list() ) {
213 186 $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
214 - wp_enqueue_script( 'pll_widgets', plugins_url( '/js/build/widgets' . $suffix . '.js', POLYLANG_ROOT_FILE ), array( 'jquery' ), POLYLANG_VERSION, true );
187 + wp_enqueue_script( 'pll_widgets', plugins_url( '/js/widgets' . $suffix . '.js', POLYLANG_FILE ), array( 'jquery' ), POLYLANG_VERSION, true );
215 188 $this->localize_scripts();
216 189 }
217 190 }
218 191
@@ -219,12 +192,26 @@
219 192 /**
220 193 * Localize scripts.
221 194 *
222 195 * @since 2.4.0
223 - *
224 - * @return void
225 196 */
226 197 public function localize_scripts() {
198 + if ( wp_script_is( 'pll_classic-editor', 'enqueued' ) ) {
199 + wp_localize_script(
200 + 'pll_classic-editor',
201 + 'confirm_text',
202 + __( 'You are about to overwrite an existing translation. Are you sure you want to proceed?', 'polylang' )
203 + );
204 + }
205 +
206 + if ( wp_script_is( 'pll_block-editor', 'enqueued' ) ) {
207 + wp_localize_script(
208 + 'pll_block-editor',
209 + 'confirm_text',
210 + __( 'You are about to overwrite an existing translation. Are you sure you want to proceed?', 'polylang' )
211 + );
212 + }
213 +
227 214 if ( wp_script_is( 'pll_widgets', 'enqueued' ) ) {
228 215 wp_localize_script(
229 216 'pll_widgets',
230 217 'pll_widgets',
@@ -247,10 +234,8 @@
247 234 * when options.data is an empty string (GET request with the method 'load')
248 235 * see: https://wordpress.org/support/topic/invalid-url-during-wordpress-new-dashboard-widget-operation
249 236 *
250 237 * @since 1.4
251 - *
252 - * @return void
253 238 */
254 239 public function admin_print_footer_scripts() {
255 240 global $post_ID, $tag_ID;
256 241
@@ -267,44 +252,34 @@
267 252 $arr = wp_json_encode( $params );
268 253 ?>
269 254 <script type="text/javascript">
270 255 if (typeof jQuery != 'undefined') {
271 - jQuery(
272 - function( $ ){
273 - $.ajaxPrefilter( function ( options, originalOptions, jqXHR ) {
274 - if ( -1 != options.url.indexOf( ajaxurl ) || -1 != ajaxurl.indexOf( options.url ) ) {
275 -
276 - function addStringParameters() {
277 - if ( 'undefined' === typeof options.data || '' === options.data ) {
278 - options.data = '<?php echo $str; // phpcs:ignore WordPress.Security.EscapeOutput ?>';
256 + (function($){
257 + $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
258 + if ( -1 != options.url.indexOf( ajaxurl ) || -1 != ajaxurl.indexOf( options.url ) ) {
259 + if ( 'undefined' === typeof options.data ) {
260 + options.data = ( 'get' === options.type.toLowerCase() ) ? '<?php echo $str; // phpcs:ignore WordPress.Security.EscapeOutput ?>' : <?php echo $arr; // phpcs:ignore WordPress.Security.EscapeOutput ?>;
261 + } else {
262 + if ( 'string' === typeof options.data ) {
263 + if ( '' === options.data && 'get' === options.type.toLowerCase() ) {
264 + options.url = options.url+'&<?php echo $str; // phpcs:ignore WordPress.Security.EscapeOutput ?>';
279 265 } else {
280 - options.data = options.data + '&<?php echo $str; // phpcs:ignore WordPress.Security.EscapeOutput ?>';
266 + try {
267 + var o = $.parseJSON(options.data);
268 + o = $.extend(o, <?php echo $arr; // phpcs:ignore WordPress.Security.EscapeOutput ?>);
269 + options.data = JSON.stringify(o);
270 + }
271 + catch(e) {
272 + options.data = '<?php echo $str; // phpcs:ignore WordPress.Security.EscapeOutput ?>&'+options.data;
273 + }
281 274 }
282 - }
283 -
284 - /*
285 - * options.processData set to true is the default jQuery process where the data is converted in a query string by using jQuery.param().
286 - * This step is done before applying filters. Thus here the options.data is already a string in this case.
287 - * @See https://github.com/jquery/jquery/blob/3.5.1/src/ajax.js#L563-L569 jQuery ajax function.
288 - */
289 - if ( options.processData ) {
290 - addStringParameters();
291 275 } else {
292 - /*
293 - * If options.processData is set to false data could be undefined or pass as a string.
294 - * So data as to be processed as if options.processData is set to true.
295 - */
296 - if ( 'undefined' === typeof options.data || 'string' === typeof options.data ) {
297 - addStringParameters();
298 - } else {
299 - // Otherwise options.data is probably an object.
300 - options.data = Object.assign( options.data, <?php echo $arr; // phpcs:ignore WordPress.Security.EscapeOutput ?> );
301 - }
276 + options.data = $.extend(options.data, <?php echo $arr; // phpcs:ignore WordPress.Security.EscapeOutput ?>);
302 277 }
303 278 }
304 - });
305 - }
306 - );
279 + }
280 + });
281 + })(jQuery)
307 282 }
308 283 </script>
309 284 <?php
310 285 }
@@ -312,10 +287,8 @@
312 287 /**
313 288 * Sets the admin current language, used to filter the content
314 289 *
315 290 * @since 2.0
316 - *
317 - * @return void
318 291 */
319 292 public function set_current_language() {
320 293 $this->curlang = $this->filter_lang;
321 294
@@ -321,9 +294,9 @@
321 294
322 295 // Edit Post
323 296 if ( isset( $_REQUEST['pll_post_id'] ) && $lang = $this->model->post->get_language( (int) $_REQUEST['pll_post_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
324 297 $this->curlang = $lang;
325 - } elseif ( 'post.php' === $GLOBALS['pagenow'] && isset( $_GET['post'] ) && $this->model->is_translated_post_type( get_post_type( (int) $_GET['post'] ) ) && $lang = $this->model->post->get_language( (int) $_GET['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
298 + } elseif ( 'post.php' === $GLOBALS['pagenow'] && isset( $_GET['post'] ) && $lang = $this->model->post->get_language( (int) $_GET['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
326 299 $this->curlang = $lang;
327 300 } elseif ( 'post-new.php' === $GLOBALS['pagenow'] && ( empty( $_GET['post_type'] ) || $this->model->is_translated_post_type( sanitize_key( $_GET['post_type'] ) ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
328 301 $this->curlang = empty( $_GET['new_lang'] ) ? $this->pref_lang : $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
329 302 }
@@ -328,14 +301,15 @@
328 301 $this->curlang = empty( $_GET['new_lang'] ) ? $this->pref_lang : $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
329 302 }
330 303
331 304 // Edit Term
332 - elseif ( isset( $_REQUEST['pll_term_id'] ) && $lang = $this->model->term->get_language( (int) $_REQUEST['pll_term_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
305 + // FIXME 'edit-tags.php' for backward compatibility with WP < 4.5
306 + elseif ( in_array( $GLOBALS['pagenow'], array( 'edit-tags.php', 'term.php' ) ) && isset( $_GET['tag_ID'] ) && $lang = $this->model->term->get_language( (int) $_GET['tag_ID'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
333 307 $this->curlang = $lang;
334 - } elseif ( in_array( $GLOBALS['pagenow'], array( 'edit-tags.php', 'term.php' ) ) && isset( $_GET['taxonomy'] ) && $this->model->is_translated_taxonomy( sanitize_key( $_GET['taxonomy'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
335 - if ( isset( $_GET['tag_ID'] ) && $lang = $this->model->term->get_language( (int) $_GET['tag_ID'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
336 - $this->curlang = $lang;
337 - } elseif ( ! empty( $_GET['new_lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
308 + } elseif ( isset( $_REQUEST['pll_term_id'] ) && $lang = $this->model->term->get_language( (int) $_REQUEST['pll_term_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
309 + $this->curlang = $lang;
310 + } elseif ( 'edit-tags.php' === $GLOBALS['pagenow'] && isset( $_GET['taxonomy'] ) && $this->model->is_translated_taxonomy( sanitize_key( $_GET['taxonomy'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
311 + if ( ! empty( $_GET['new_lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
338 312 $this->curlang = $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
339 313 } elseif ( empty( $this->curlang ) ) {
340 314 $this->curlang = $this->pref_lang;
341 315 }
@@ -344,17 +318,8 @@
344 318 // Ajax
345 319 if ( wp_doing_ajax() && ! empty( $_REQUEST['lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
346 320 $this->curlang = $this->model->get_language( sanitize_key( $_REQUEST['lang'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
347 321 }
348 -
349 - // Inform that the admin language has been set.
350 - if ( $this->curlang ) {
351 - /** This action is documented in frontend/choose-lang.php */
352 - do_action( 'pll_language_defined', $this->curlang->slug, $this->curlang );
353 - } else {
354 - /** This action is documented in include/class-polylang.php */
355 - do_action( 'pll_no_language_defined' ); // To load overridden textdomains.
356 - }
357 322 }
358 323
359 324 /**
360 325 * Defines the backend language and the admin language filter based on user preferences
@@ -359,10 +324,8 @@
359 324 /**
360 325 * Defines the backend language and the admin language filter based on user preferences
361 326 *
362 327 * @since 1.2.3
363 - *
364 - * @return void
365 328 */
366 329 public function init_user() {
367 330 // Language for admin language filter: may be empty
368 331 // $_GET['lang'] is numeric when editing a language, not when selecting a new language in the filter
@@ -376,21 +339,28 @@
376 339 // Set preferred language for use when saving posts and terms: must not be empty
377 340 $this->pref_lang = empty( $this->filter_lang ) ? $this->model->get_language( $this->options['default_lang'] ) : $this->filter_lang;
378 341
379 342 /**
380 - * Filters the preferred language on admin side.
381 - * The preferred language is used for example to determine the language of a new post.
343 + * Filter the preferred language on admin side
344 + * The preferred language is used for example to determine the language of a new post
382 345 *
383 346 * @since 1.2.3
384 347 *
385 - * @param PLL_Language $pref_lang Preferred language.
348 + * @param object $pref_lang preferred language
386 349 */
387 350 $this->pref_lang = apply_filters( 'pll_admin_preferred_language', $this->pref_lang );
388 351
389 352 $this->set_current_language();
390 353
391 - // Plugin i18n, only needed for backend.
392 - load_plugin_textdomain( 'polylang' );
354 + // Inform that the admin language has been set
355 + // Only if the admin language is one of the Polylang defined language
356 + if ( $curlang = $this->model->get_language( get_user_locale() ) ) {
357 + /** This action is documented in frontend/choose-lang.php */
358 + do_action( 'pll_language_defined', $curlang->slug, $curlang );
359 + } else {
360 + /** This action is documented in include/class-polylang.php */
361 + do_action( 'pll_no_language_defined' ); // to load overridden textdomains
362 + }
393 363 }
394 364
395 365 /**
396 366 * Avoids parsing a tax query when all languages are requested
@@ -395,9 +365,9 @@
395 365 /**
396 366 * Avoids parsing a tax query when all languages are requested
397 367 * Fixes https://wordpress.org/support/topic/notice-undefined-offset-0-in-wp-includesqueryphp-on-line-3877 introduced in WP 4.1
398 368 *
399 - * @see https://core.trac.wordpress.org/ticket/31246 the suggestion of @boonebgorges.
369 + * @see the suggestion of @boonebgorges, https://core.trac.wordpress.org/ticket/31246
400 370 *
401 371 * @since 1.6.5
402 372 *
403 373 * @param array $qvars
@@ -411,14 +381,13 @@
411 381 return $qvars;
412 382 }
413 383
414 384 /**
415 - * Adds the languages list in admin bar for the admin languages filter.
385 + * Adds the languages list in admin bar for the admin languages filter
416 386 *
417 387 * @since 0.9
418 388 *
419 - * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar global object.
420 - * @return void
389 + * @param object $wp_admin_bar
421 390 */
422 391 public function admin_bar_menu( $wp_admin_bar ) {
423 392 $all_item = (object) array(
424 393 'slug' => 'all',
@@ -469,6 +438,14 @@
469 438 'meta' => 'all' === $lang->slug ? array() : array( 'lang' => esc_attr( $lang->get_locale( 'display' ) ) ),
470 439 )
471 440 );
472 441 }
442 + }
443 + /**
444 + * Instantiate PLL_Wizard_Pro class.
445 + *
446 + * @since 2.7
447 + */
448 + public function instantiate_wizard_pro() {
449 + $this->wizard_pro = new PLL_Wizard_Pro( $this );
473 450 }
474 451 }