PluginProbe
Polylang / 2.1.3
Polylang v2.1.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
polylang / admin / admin-base.php

admin-base.php in Polylang 2.1.3, at admin/admin-base.php

355 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 /**
4 * Base class for both admin
5 *
6 * @since 1.8
7 */
8 class PLL_Admin_Base extends PLL_Base {
9 public $filter_lang, $curlang, $pref_lang;
10
11 /**
12 * Loads the polylang text domain
13 * Setups actions needed on all admin pages
14 *
15 * @since 1.8
16 *
17 * @param object $links_model
18 */
19 public function __construct( &$links_model ) {
20 parent::__construct( $links_model );
21
22 // Plugin i18n, only needed for backend
23 load_plugin_textdomain( 'polylang', false, basename( POLYLANG_DIR ).'/languages' );
24
25 // Adds the link to the languages panel in the WordPress admin menu
26 add_action( 'admin_menu', array( $this, 'add_menus' ) );
27
28 // Setup js scripts and css styles
29 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
30 add_action( 'admin_print_footer_scripts', array( $this, 'admin_print_footer_scripts' ) );
31
32 // Lingotek
33 if ( ! defined( 'PLL_LINGOTEK_AD' ) || PLL_LINGOTEK_AD ) {
34 require_once POLYLANG_DIR . '/lingotek/lingotek.php';
35 }
36 }
37
38 /**
39 * Setups filters and action needed on all admin pages and on plugins page
40 * Loads the settings pages or the filters base on the request
41 *
42 * @since 1.2
43 *
44 * @param object $links_model
45 */
46 public function init() {
47 if ( ! $this->model->get_languages_list() ) {
48 return;
49 }
50
51 $this->links = new PLL_Admin_Links( $this ); // FIXME needed here ?
52 $this->static_pages = new PLL_Admin_Static_Pages( $this ); // FIXME needed here ?
53 $this->filters_links = new PLL_Filters_Links( $this ); // FIXME needed here ?
54
55 // Filter admin language for users
56 // We must not call user info before WordPress defines user roles in wp-settings.php
57 add_filter( 'setup_theme', array( $this, 'init_user' ) );
58 add_filter( 'request', array( $this, 'request' ) );
59
60 // Adds the languages in admin bar
61 add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 100 ); // 100 determines the position
62 }
63
64 /**
65 * Adds the link to the languages panel in the WordPress admin menu
66 *
67 * @since 0.1
68 */
69 public function add_menus() {
70 // Prepare the list of tabs
71 $tabs = array( 'lang' => __( 'Languages','polylang' ) );
72
73 // Only if at least one language has been created
74 if ( $this->model->get_languages_list() ) {
75 $tabs['strings'] = __( 'Strings translations', 'polylang' );
76 }
77
78 $tabs['settings'] = __( 'Settings', 'polylang' );
79
80 /**
81 * Filter the list of tabs in Polylang settings
82 *
83 * @since 1.5.1
84 *
85 * @param array $tabs list of tab names
86 */
87 $tabs = apply_filters( 'pll_settings_tabs', $tabs );
88
89 foreach ( $tabs as $tab => $title ) {
90 $page = 'lang' === $tab ? 'mlang' : "mlang_$tab";
91 if ( empty( $parent ) ) {
92 $parent = $page;
93 add_menu_page( $title, __( 'Languages','polylang' ), 'manage_options', $page, null , 'dashicons-translation' );
94 }
95
96 add_submenu_page( $parent, $title, $title, 'manage_options', $page , array( $this, 'languages_page' ) );
97 }
98 }
99
100 /**
101 * Setup js scripts & css styles ( only on the relevant pages )
102 *
103 * @since 0.6
104 */
105 public function admin_enqueue_scripts() {
106 $screen = get_current_screen();
107 if ( empty( $screen ) ) {
108 return;
109 }
110
111 $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
112
113 // For each script:
114 // 0 => the pages on which to load the script
115 // 1 => the scripts it needs to work
116 // 2 => 1 if loaded even if languages have not been defined yet, 0 otherwise
117 // 3 => 1 if loaded in footer
118 // FIXME: check if I can load more scripts in footer
119 $scripts = array(
120 'post' => array( array( 'post', 'media', 'async-upload', 'edit' ), array( 'jquery', 'wp-ajax-response', 'post', 'jquery-ui-autocomplete' ), 0 , 1 ),
121 'media' => array( array( 'upload' ), array( 'jquery' ), 0 , 1 ),
122 'term' => array( array( 'edit-tags', 'term' ), array( 'jquery', 'wp-ajax-response', 'jquery-ui-autocomplete' ), 0, 1 ),
123 'user' => array( array( 'profile', 'user-edit' ), array( 'jquery' ), 0 , 0 ),
124 );
125
126 foreach ( $scripts as $script => $v ) {
127 if ( in_array( $screen->base, $v[0] ) && ( $v[2] || $this->model->get_languages_list() ) ) {
128 wp_enqueue_script( 'pll_' . $script, plugins_url( '/js/' . $script . $suffix . '.js', POLYLANG_FILE ), $v[1], POLYLANG_VERSION, $v[3] );
129 }
130 }
131
132 wp_enqueue_style( 'polylang_admin', plugins_url( '/css/admin' . $suffix . '.css', POLYLANG_FILE ), array(), POLYLANG_VERSION );
133 }
134
135 /**
136 * Sets pll_ajax_backend on all backend ajax request
137 * The final goal is to detect if an ajax request is made on admin or frontend
138 *
139 * Takes care to various situations:
140 * when the ajax request has no options.data thanks to ScreenfeedFr
141 * see: https://wordpress.org/support/topic/ajaxprefilter-may-not-work-as-expected
142 * when options.data is a json string
143 * see: https://wordpress.org/support/topic/polylang-breaking-third-party-ajax-requests-on-admin-panels
144 * when options.data is an empty string (GET request with the method 'load')
145 * see: https://wordpress.org/support/topic/invalid-url-during-wordpress-new-dashboard-widget-operation
146 *
147 * @since 1.4
148 */
149 public function admin_print_footer_scripts() {
150 global $post_ID;
151
152 $params = array( 'pll_ajax_backend' => 1 );
153 if ( ! empty( $post_ID ) ) {
154 $params = array_merge( $params, array( 'pll_post_id' => (int) $post_ID ) );
155 }
156
157 $str = http_build_query( $params );
158 $arr = json_encode( $params );
159 ?>
160 <script type="text/javascript">
161 if (typeof jQuery != 'undefined') {
162 (function($){
163 $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
164 if ( -1 != options.url.indexOf( ajaxurl ) || -1 != ajaxurl.indexOf( options.url ) ) {
165 if ( 'undefined' === typeof options.data ) {
166 options.data = ( 'get' === options.type.toLowerCase() ) ? '<?php echo $str;?>' : <?php echo $arr;?>;
167 } else {
168 if ( 'string' === typeof options.data ) {
169 if ( '' === options.data && 'get' === options.type.toLowerCase() ) {
170 options.url = options.url+'&<?php echo $str;?>';
171 } else {
172 try {
173 o = $.parseJSON(options.data);
174 o = $.extend(o, <?php echo $arr;?>);
175 options.data = JSON.stringify(o);
176 }
177 catch(e) {
178 options.data = '<?php echo $str;?>&'+options.data;
179 }
180 }
181 } else {
182 options.data = $.extend(options.data, <?php echo $arr;?>);
183 }
184 }
185 }
186 });
187 })(jQuery)
188 }
189 </script><?php
190 }
191
192 /**
193 * Sets the admin current language, used to filter the content
194 *
195 * @since 2.0
196 */
197 public function set_current_language() {
198 $this->curlang = $this->filter_lang;
199
200 // Edit Post
201 if ( isset( $_REQUEST['pll_post_id'] ) && $lang = $this->model->post->get_language( (int) $_REQUEST['pll_post_id'] ) ) {
202 $this->curlang = $lang;
203 } elseif ( 'post.php' === $GLOBALS['pagenow'] && isset( $_GET['post'] ) && is_numeric( $_GET['post'] ) && $lang = $this->model->post->get_language( (int) $_GET['post'] ) ) {
204 $this->curlang = $lang;
205 } elseif ( 'post-new.php' === $GLOBALS['pagenow'] && ( empty( $_GET['post_type'] ) || $this->model->is_translated_post_type( $_GET['post_type'] ) ) ) {
206 $this->curlang = empty( $_GET['new_lang'] ) ? $this->pref_lang : $this->model->get_language( $_GET['new_lang'] );
207 }
208
209 // Edit Term
210 // FIXME 'edit-tags.php' for backward compatibility with WP < 4.5
211 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'] ) ) {
212 $this->curlang = $lang;
213 } elseif ( 'edit-tags.php' === $GLOBALS['pagenow'] && isset( $_GET['taxonomy'] ) && $this->model->is_translated_taxonomy( $_GET['taxonomy'] ) ) {
214 if ( ! empty( $_GET['new_lang'] ) ) {
215 $this->curlang = $this->model->get_language( $_GET['new_lang'] );
216 } elseif ( empty( $this->curlang ) ) {
217 $this->curlang = $this->pref_lang;
218 }
219 }
220
221 // Ajax
222 if ( defined( 'DOING_AJAX' ) && DOING_AJAX && ! empty( $_REQUEST['lang'] ) ) {
223 $this->curlang = $this->model->get_language( $_REQUEST['lang'] );
224 }
225 }
226
227 /**
228 * Defines the backend language and the admin language filter based on user preferences
229 *
230 * @since 1.2.3
231 */
232 public function init_user() {
233 // Backend locale
234 // FIXME: Backward compatibility with WP < 4.7
235 if ( version_compare( $GLOBALS['wp_version'], '4.7alpha', '<' ) ) {
236 add_filter( 'locale', array( $this, 'get_locale' ) );
237 }
238
239 // Language for admin language filter: may be empty
240 // $_GET['lang'] is numeric when editing a language, not when selecting a new language in the filter
241 if ( ! defined( 'DOING_AJAX' ) && ! empty( $_GET['lang'] ) && ! is_numeric( $_GET['lang'] ) && current_user_can( 'edit_user', $user_id = get_current_user_id() ) ) {
242 update_user_meta( $user_id, 'pll_filter_content', ( $lang = $this->model->get_language( $_GET['lang'] ) ) ? $lang->slug : '' );
243 }
244
245 $this->filter_lang = $this->model->get_language( get_user_meta( get_current_user_id(), 'pll_filter_content', true ) );
246
247 // Set preferred language for use when saving posts and terms: must not be empty
248 $this->pref_lang = empty( $this->filter_lang ) ? $this->model->get_language( $this->options['default_lang'] ) : $this->filter_lang;
249
250 /**
251 * Filter the preferred language on amin side
252 * The preferred language is used for example to determine the language of a new post
253 *
254 * @since 1.2.3
255 *
256 * @param object $pref_lang preferred language
257 */
258 $this->pref_lang = apply_filters( 'pll_admin_preferred_language', $this->pref_lang );
259
260 $this->set_current_language();
261
262 // Inform that the admin language has been set
263 // Only if the admin language is one of the Polylang defined language
264 // FIXME test get_user_locale for backward compatibility with WP 4.7
265 if ( $curlang = $this->model->get_language( function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale() ) ) {
266 // FIXME: Backward compatibility with WP < 4.7
267 if ( version_compare( $GLOBALS['wp_version'], '4.7alpha', '<' ) ) {
268 $GLOBALS['text_direction'] = $curlang->is_rtl ? 'rtl' : 'ltr'; // force text direction according to language setting
269 }
270
271 /** This action is documented in frontend/choose-lang.php */
272 do_action( 'pll_language_defined', $curlang->slug, $curlang );
273 } else {
274 /** This action is documented in include/class-polylang.php */
275 do_action( 'pll_no_language_defined' ); // to load overriden textdomains
276 }
277 }
278
279 /**
280 * Avoids parsing a tax query when all languages are requested
281 * Fixes https://wordpress.org/support/topic/notice-undefined-offset-0-in-wp-includesqueryphp-on-line-3877 introduced in WP 4.1
282 * @see the suggestion of @boonebgorges, https://core.trac.wordpress.org/ticket/31246
283 *
284 * @since 1.6.5
285 *
286 * @param array $qvars
287 * @return array
288 */
289 public function request( $qvars ) {
290 if ( isset( $qvars['lang'] ) && 'all' === $qvars['lang'] ) {
291 unset( $qvars['lang'] );
292 }
293
294 return $qvars;
295 }
296
297 /**
298 * Get the locale based on user preference
299 * FIXME: Backward compatibility with WP < 4.7
300 *
301 * @since 0.4
302 *
303 * @param string $locale
304 * @return string modified locale
305 */
306 public function get_locale( $locale ) {
307 return ( $loc = get_user_meta( get_current_user_id(), 'locale', 'true' ) ) ? $loc : $locale;
308 }
309
310 /**
311 * Adds the languages list in admin bar for the admin languages filter
312 *
313 * @since 0.9
314 *
315 * @param object $wp_admin_bar
316 */
317 public function admin_bar_menu( $wp_admin_bar ) {
318 $url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
319
320 $all_item = (object) array(
321 'slug' => 'all',
322 'name' => __( 'Show all languages', 'polylang' ),
323 'flag' => '<span class="ab-icon"></span>',
324 );
325
326 $selected = empty( $this->filter_lang ) ? $all_item : $this->filter_lang;
327
328 $title = sprintf(
329 '<span class="ab-label"%s>%s</span>',
330 'all' === $selected->slug ? '' : sprintf( ' lang="%s"', esc_attr( $selected->get_locale( 'display' ) ) ),
331 esc_html( $selected->name )
332 );
333
334 $wp_admin_bar->add_menu( array(
335 'id' => 'languages',
336 'title' => $selected->flag . $title,
337 'meta' => array( 'title' => __( 'Filters content by language', 'polylang' ) ),
338 ) );
339
340 foreach ( array_merge( array( $all_item ), $this->model->get_languages_list() ) as $lang ) {
341 if ( $selected->slug === $lang->slug ) {
342 continue;
343 }
344
345 $wp_admin_bar->add_menu( array(
346 'parent' => 'languages',
347 'id' => $lang->slug,
348 'title' => $lang->flag . esc_html( $lang->name ),
349 'href' => esc_url( add_query_arg( 'lang', $lang->slug, remove_query_arg( 'paged', $url ) ) ),
350 'meta' => 'all' === $lang->slug ? array() : array( 'lang' => esc_attr( $lang->get_locale( 'display' ) ) ),
351 ) );
352 }
353 }
354 }
355