| 1 |
<?php |
| 2 |
|
| 3 |
// functions common to all admin panels |
| 4 |
class Polylang_Admin_Base extends Polylang_Base { |
| 5 |
function __construct() { |
| 6 |
parent::__construct(); |
| 7 |
|
| 8 |
// filter admin language for users |
| 9 |
add_filter('locale', array(&$this, 'get_locale')); |
| 10 |
|
| 11 |
// set user preferences |
| 12 |
add_action('admin_init', array(&$this, 'admin_init_base')); |
| 13 |
|
| 14 |
// adds the link to the languages panel in the wordpress admin menu |
| 15 |
add_action('admin_menu', array(&$this, 'add_menus')); |
| 16 |
|
| 17 |
// setup js scripts and css styles |
| 18 |
add_action('admin_enqueue_scripts', array(&$this, 'admin_enqueue_scripts')); |
| 19 |
} |
| 20 |
|
| 21 |
// returns the locale based on user preference |
| 22 |
function get_locale($locale) { |
| 23 |
// get_current_user_id uses wp_get_current_user which may not be available the first time(s) get_locale is called |
| 24 |
return function_exists('wp_get_current_user') && ($loc = get_user_meta(get_current_user_id(), 'user_lang', 'true')) ? $loc : $locale; |
| 25 |
} |
| 26 |
|
| 27 |
// set user preferences |
| 28 |
function admin_init_base() { |
| 29 |
if (!$languages = $this->get_languages_list()) |
| 30 |
return; |
| 31 |
|
| 32 |
// set text direction if the user set its own language |
| 33 |
$locale = get_locale(); |
| 34 |
foreach($languages as $lang) { |
| 35 |
if ($locale == $lang->description) { |
| 36 |
$GLOBALS['wp_locale']->text_direction = get_metadata('term', $lang->term_id, '_rtl', true) ? 'rtl' : 'ltr'; |
| 37 |
$GLOBALS['l10n']['pll_string'] = $this->mo_import($lang); |
| 38 |
break; |
| 39 |
} |
| 40 |
} |
| 41 |
|
| 42 |
// set user meta when choosing to filter content by language |
| 43 |
// $_GET[lang] is used in ajax 'tag suggest' and is numeric when editing a language |
| 44 |
if (!defined('DOING_AJAX') && !empty($_GET['lang']) && !is_numeric($_GET['lang'])) |
| 45 |
update_user_meta(get_current_user_id(), 'pll_filter_content', ($lang = $this->get_language($_GET['lang'])) ? $lang->slug : ''); |
| 46 |
|
| 47 |
// adds the languages in admin bar |
| 48 |
// FIXME: OK for WP 3.2 and newer (the admin bar is not displayed on admin side for WP 3.1) |
| 49 |
add_action('admin_bar_menu', array(&$this, 'admin_bar_menu'), 100); // 100 determines the position |
| 50 |
} |
| 51 |
|
| 52 |
// adds the link to the languages panel in the wordpress admin menu |
| 53 |
function add_menus() { |
| 54 |
add_submenu_page('options-general.php', $title = __('Languages', 'polylang'), $title, 'manage_options', 'mlang', array(&$this, 'languages_page')); |
| 55 |
} |
| 56 |
|
| 57 |
// setup js scripts & css styles (only on the relevant pages) |
| 58 |
function admin_enqueue_scripts() { |
| 59 |
$screen = get_current_screen(); |
| 60 |
$suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min'; |
| 61 |
|
| 62 |
// for each script: |
| 63 |
// 0 => the pages on which to load the script |
| 64 |
// 1 => the scripts it needs to work |
| 65 |
// 2 => 1 if loaded even if languages have not been defined yet, 0 otherwise |
| 66 |
$scripts = array( |
| 67 |
'admin' => array( array('settings_page_mlang'), array('jquery', 'wp-ajax-response', 'postbox'), 1 ), |
| 68 |
'post' => array( array('post', 'media', 'async-upload', 'edit'), array('jquery', 'wp-ajax-response'), 0 ), |
| 69 |
'term' => array( array('edit-tags'), array('jquery', 'wp-ajax-response'), 0 ), |
| 70 |
'user' => array( array('profile', 'user-edit'), array('jquery'), 0 ), |
| 71 |
); |
| 72 |
|
| 73 |
foreach ($scripts as $script => $v) |
| 74 |
if (in_array($screen->base, $v[0]) && ($v[2] || $this->get_languages_list())) |
| 75 |
wp_enqueue_script('pll_'.$script, POLYLANG_URL .'/js/'.$script.$suffix.'.js', $v[1], POLYLANG_VERSION); |
| 76 |
|
| 77 |
if (in_array($screen->base, array('settings_page_mlang', 'post', 'edit-tags', 'edit', 'upload', 'media'))) |
| 78 |
wp_enqueue_style('polylang_admin', POLYLANG_URL .'/css/admin'.$suffix.'.css', array(), POLYLANG_VERSION); |
| 79 |
} |
| 80 |
|
| 81 |
// downloads mofiles |
| 82 |
function download_mo($locale, $upgrade = false) { |
| 83 |
global $wp_version; |
| 84 |
$mofile = WP_LANG_DIR."/$locale.mo"; |
| 85 |
|
| 86 |
// does file exists ? |
| 87 |
if ((file_exists($mofile) && !$upgrade) || $locale == 'en_US') |
| 88 |
return true; |
| 89 |
|
| 90 |
// does language directory exists ? |
| 91 |
if (!is_dir(WP_LANG_DIR)) { |
| 92 |
if (!@mkdir(WP_LANG_DIR)) |
| 93 |
return false; |
| 94 |
} |
| 95 |
|
| 96 |
// will first look in tags/ (most languages) then in branches/ (only Greek ?) |
| 97 |
$base = 'http://svn.automattic.com/wordpress-i18n/'.$locale; |
| 98 |
$bases = array($base.'/tags/', $base.'/branches/'); |
| 99 |
|
| 100 |
foreach ($bases as $base) { |
| 101 |
// get all the versions available in the subdirectory |
| 102 |
$resp = wp_remote_get($base); |
| 103 |
if (is_wp_error($resp) || 200 != $resp['response']['code']) |
| 104 |
continue; |
| 105 |
|
| 106 |
preg_match_all('#>([0-9\.]+)\/#', $resp['body'], $matches); |
| 107 |
if (empty($matches[1])) |
| 108 |
continue; |
| 109 |
|
| 110 |
rsort($matches[1]); // sort from newest to oldest |
| 111 |
$versions = $matches[1]; |
| 112 |
|
| 113 |
$newest = $upgrade ? $upgrade : $wp_version; |
| 114 |
foreach ($versions as $key=>$version) { |
| 115 |
// will not try to download a too recent mofile |
| 116 |
if (version_compare($version, $newest, '>')) |
| 117 |
unset($versions[$key]); |
| 118 |
// will not download an older version if we are upgrading |
| 119 |
if ($upgrade && version_compare($version, $wp_version, '<=')) |
| 120 |
unset($versions[$key]); |
| 121 |
} |
| 122 |
|
| 123 |
$versions = array_splice($versions, 0, 5); // reduce the number of versions to test to 5 |
| 124 |
$args = array('timeout' => 30, 'stream' => true); |
| 125 |
|
| 126 |
// try to download the file |
| 127 |
foreach ($versions as $version) { |
| 128 |
$resp = wp_remote_get($base."$version/messages/$locale.mo", $args + array('filename' => $mofile)); |
| 129 |
if (is_wp_error($resp) || 200 != $resp['response']['code']) { |
| 130 |
unlink($mofile); // otherwise we download a gzipped 404 page |
| 131 |
continue; |
| 132 |
} |
| 133 |
// try to download ms and continents-cities files if exist (will not return false if failed) |
| 134 |
// with new files introduced in WP 3.4 |
| 135 |
foreach (array('ms', 'continents-cities', 'admin', 'admin-network') as $file) { |
| 136 |
$resp = wp_remote_get($base."$version/messages/$file-$locale.mo", $args + array('filename' => WP_LANG_DIR."/$file-$locale.mo")); |
| 137 |
if (is_wp_error($resp) || 200 != $resp['response']['code']) |
| 138 |
unlink(WP_LANG_DIR."/$file-$locale.mo"); |
| 139 |
} |
| 140 |
// try to download theme files if exist (will not return false if failed) |
| 141 |
// FIXME not updated when the theme is updated outside a core update |
| 142 |
foreach (array('twentyten', 'twentyeleven', 'twentytwelve', 'twentythirteen') as $theme) { |
| 143 |
if (!is_dir($theme_dir = get_theme_root()."/$theme/languages")) |
| 144 |
continue; // the theme is not present |
| 145 |
|
| 146 |
$resp = wp_remote_get($base."$version/messages/$theme/$locale.mo", $args + array('filename' => "$theme_dir/$locale.mo")); |
| 147 |
if (is_wp_error($resp) || 200 != $resp['response']['code']) |
| 148 |
unlink("$theme_dir/$locale.mo"); |
| 149 |
} |
| 150 |
return true; |
| 151 |
} |
| 152 |
} |
| 153 |
// we did not succeeded to download a file :( |
| 154 |
return false; |
| 155 |
} |
| 156 |
|
| 157 |
// returns options available for the language switcher (menu or widget) |
| 158 |
function get_switcher_options($type = 'widget', $key ='string') { |
| 159 |
$options = array( |
| 160 |
'show_names' => array('string' => __('Displays language names', 'polylang'), 'default' => 1), |
| 161 |
'show_flags' => array('string' => __('Displays flags', 'polylang'), 'default' => 0), |
| 162 |
'force_home' => array('string' => __('Forces link to front page', 'polylang'), 'default' => 0), |
| 163 |
'hide_current' => array('string' => __('Hides the current language', 'polylang'), 'default' => 0), |
| 164 |
); |
| 165 |
|
| 166 |
if ($type != 'menu') |
| 167 |
$options['dropdown'] = array('string' => __('Displays as dropdown', 'polylang'), 'default' => 0); |
| 168 |
|
| 169 |
return array_map(create_function('$v', "return \$v['$key'];"), $options); |
| 170 |
} |
| 171 |
|
| 172 |
// register strings for translation making sure it is not duplicate or empty |
| 173 |
function register_string($name, $string, $context = 'polylang', $multiline = false) { |
| 174 |
// backward compatibility with Polylang older than 1.1 |
| 175 |
if (is_bool($context)) { |
| 176 |
$multiline = $context; |
| 177 |
$context = 'polylang'; |
| 178 |
} |
| 179 |
|
| 180 |
$to_register = compact('name', 'string', 'context', 'multiline'); |
| 181 |
if (!in_array($to_register, $this->strings) && $to_register['string']) |
| 182 |
$this->strings[] = $to_register; |
| 183 |
} |
| 184 |
|
| 185 |
// adds the languages in admin bar |
| 186 |
function admin_bar_menu($wp_admin_bar) { |
| 187 |
$url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; |
| 188 |
|
| 189 |
// $_GET['lang'] is numeric when editing a language, not when selecting a new language in the filter |
| 190 |
$selected = !empty($_GET['lang']) && !is_numeric($_GET['lang']) && ($lang = $this->get_language($_GET['lang'])) ? $lang->slug : |
| 191 |
(($lg = get_user_meta(get_current_user_id(), 'pll_filter_content', true)) ? $lg : 'all'); |
| 192 |
|
| 193 |
$all_item = array((object) array('slug' => 'all', 'name' => __('Show all languages', 'polylang'))); |
| 194 |
|
| 195 |
$wp_admin_bar->add_menu(array( |
| 196 |
'id' => 'languages', |
| 197 |
'title' => __('Languages', 'polylang'), |
| 198 |
'meta' => array('title' => __('Filters content by language', 'polylang')), |
| 199 |
)); |
| 200 |
|
| 201 |
foreach (array_merge($all_item, $this->get_languages_list()) as $lang) { |
| 202 |
$href = esc_url(add_query_arg('lang', $lang->slug, $url)); |
| 203 |
$wp_admin_bar->add_menu(array( |
| 204 |
'parent' => 'languages', |
| 205 |
'id' => $lang->slug, |
| 206 |
'title' => sprintf( |
| 207 |
'<input name="language" type="radio" onclick="location.href=%s" value="%s" %s /> %s', // FIXME this works but produces invalid html |
| 208 |
"'" . $href . "'", // onclick is needed for Chrome browser, thanks to RavanH for the bug report and fix |
| 209 |
esc_attr($lang->slug), |
| 210 |
$selected == $lang->slug ? 'checked="checked"' : '', |
| 211 |
esc_html($lang->name) |
| 212 |
), |
| 213 |
'href' => $href, |
| 214 |
)); |
| 215 |
} |
| 216 |
} |
| 217 |
|
| 218 |
} // class Polylang_Admin_Base |
| 219 |
|