PluginProbe
Polylang / 3.2.2
Polylang v3.2.2
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 / include / links-directory.php

links-directory.php in Polylang 3.2.2, at include/links-directory.php

279 lines 9.3 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 * Links model for use when the language code is added in url as a directory
8 * for example mysite.com/en/something
9 * implements the "links_model interface"
10 *
11 * @since 1.2
12 */
13 class PLL_Links_Directory extends PLL_Links_Permalinks {
14 /**
15 * Relative path to the home url.
16 *
17 * @var string
18 */
19 protected $home_relative;
20
21 /**
22 * Constructor.
23 *
24 * @since 1.2
25 *
26 * @param PLL_Model $model PLL_Model instance.
27 */
28 public function __construct( &$model ) {
29 parent::__construct( $model );
30
31 $this->home_relative = home_url( '/', 'relative' );
32
33 if ( did_action( 'pll_init' ) ) {
34 $this->init();
35 } else {
36 add_action( 'pll_init', array( $this, 'init' ) );
37 }
38 }
39
40 /**
41 * Called only at first object creation to avoid duplicating filters when switching blog
42 *
43 * @since 1.6
44 *
45 * @return void
46 */
47 public function init() {
48 if ( did_action( 'setup_theme' ) ) {
49 $this->add_permastruct();
50 } else {
51 add_action( 'setup_theme', array( $this, 'add_permastruct' ), 2 );
52 }
53
54 // Make sure to prepare rewrite rules when flushing
55 add_action( 'pre_option_rewrite_rules', array( $this, 'prepare_rewrite_rules' ) );
56 }
57
58 /**
59 * Adds the language code in a url.
60 * links_model interface.
61 *
62 * @since 1.2
63 *
64 * @param string $url The url to modify.
65 * @param PLL_Language $lang The language object.
66 * @return string Modified url.
67 */
68 public function add_language_to_link( $url, $lang ) {
69 if ( ! empty( $lang ) ) {
70 $base = $this->options['rewrite'] ? '' : 'language/';
71 $slug = $this->options['default_lang'] == $lang->slug && $this->options['hide_default'] ? '' : $base . $lang->slug . '/';
72 $root = ( false === strpos( $url, '://' ) ) ? $this->home_relative . $this->root : preg_replace( '#^https?://#', '://', $this->home . '/' . $this->root );
73
74 if ( false === strpos( $url, $new = $root . $slug ) ) {
75 $pattern = preg_quote( $root, '#' );
76 $pattern = '#' . $pattern . '#';
77 return preg_replace( $pattern, $new, $url, 1 ); // Only once
78 }
79 }
80 return $url;
81 }
82
83 /**
84 * Returns the url without language code
85 * links_model interface
86 *
87 * @since 1.2
88 *
89 * @param string $url url to modify
90 * @return string modified url
91 */
92 public function remove_language_from_link( $url ) {
93 $languages = array();
94
95 foreach ( $this->model->get_languages_list() as $language ) {
96 if ( ! $this->options['hide_default'] || $this->options['default_lang'] != $language->slug ) {
97 $languages[] = $language->slug;
98 }
99 }
100
101 if ( ! empty( $languages ) ) {
102 $root = ( false === strpos( $url, '://' ) ) ? $this->home_relative . $this->root : preg_replace( '#^https?://#', '://', $this->home . '/' . $this->root );
103
104 $pattern = preg_quote( $root, '#' );
105 $pattern = '#' . $pattern . ( $this->options['rewrite'] ? '' : 'language/' ) . '(' . implode( '|', $languages ) . ')(/|$)#';
106 $url = preg_replace( $pattern, $root, $url );
107 }
108 return $url;
109 }
110
111 /**
112 * Returns the language based on language code in url
113 * links_model interface
114 *
115 * @since 1.2
116 * @since 2.0 add $url argument
117 *
118 * @param string $url optional, defaults to current url
119 * @return string language slug
120 */
121 public function get_language_from_url( $url = '' ) {
122 if ( empty( $url ) ) {
123 $url = pll_get_requested_url();
124 }
125
126 $path = (string) wp_parse_url( $url, PHP_URL_PATH );
127 $root = ( false === strpos( $url, '://' ) ) ? $this->home_relative . $this->root : $this->home . '/' . $this->root;
128
129 $pattern = (string) wp_parse_url( $root . ( $this->options['rewrite'] ? '' : 'language/' ), PHP_URL_PATH );
130 $pattern = preg_quote( $pattern, '#' );
131 $pattern = '#^' . $pattern . '(' . implode( '|', $this->model->get_languages_list( array( 'fields' => 'slug' ) ) ) . ')(/|$)#';
132 return preg_match( $pattern, trailingslashit( $path ), $matches ) ? $matches[1] : ''; // $matches[1] is the slug of the requested language
133 }
134
135 /**
136 * Returns the home url in a given language.
137 * links_model interface.
138 *
139 * @since 1.3.1
140 *
141 * @param PLL_Language $lang PLL_Language object.
142 * @return string
143 */
144 public function home_url( $lang ) {
145 $base = $this->options['rewrite'] ? '' : 'language/';
146 $slug = $this->options['default_lang'] == $lang->slug && $this->options['hide_default'] ? '' : '/' . $this->root . $base . $lang->slug;
147 return trailingslashit( $this->home . $slug );
148 }
149
150 /**
151 * Optionally removes 'language' in permalinks so that we get http://www.myblog/en/ instead of http://www.myblog/language/en/
152 *
153 * @since 1.2
154 *
155 * @return void
156 */
157 public function add_permastruct() {
158 // Language information always in front of the uri ( 'with_front' => false )
159 // The 3rd parameter structure has been modified in WP 3.4
160 // Leads to error 404 for pages when there is no language created yet
161 if ( $this->model->get_languages_list() ) {
162 add_permastruct( 'language', $this->options['rewrite'] ? '%language%' : 'language/%language%', array( 'with_front' => false ) );
163 }
164 }
165
166 /**
167 * Prepares the rewrite rules filters.
168 *
169 * @since 0.8.1
170 *
171 * @param mixed $pre Not used as the filter is used as an action.
172 * @return mixed
173 */
174 public function prepare_rewrite_rules( $pre ) {
175 // Don't modify the rules if there is no languages created yet
176 // Make sure to add filter only once and if all custom post types and taxonomies have been registered
177 if ( $this->model->get_languages_list() && did_action( 'wp_loaded' ) && ! has_filter( 'language_rewrite_rules', '__return_empty_array' ) ) {
178 // Suppress the rules created by WordPress for our taxonomy
179 add_filter( 'language_rewrite_rules', '__return_empty_array' );
180
181 foreach ( $this->get_rewrite_rules_filters() as $type ) {
182 add_filter( $type . '_rewrite_rules', array( $this, 'rewrite_rules' ) );
183 }
184
185 add_filter( 'rewrite_rules_array', array( $this, 'rewrite_rules' ) ); // needed for post type archives
186 }
187 return $pre;
188 }
189
190 /**
191 * The rewrite rules !
192 * Always make sure that the default language is at the end in case the language information is hidden for default language.
193 * Thanks to brbrbr http://wordpress.org/support/topic/plugin-polylang-rewrite-rules-not-correct.
194 *
195 * @since 0.8.1
196 *
197 * @param string[] $rules Rewrite rules.
198 * @return string[] Modified rewrite rules.
199 */
200 public function rewrite_rules( $rules ) {
201 $filter = str_replace( '_rewrite_rules', '', current_filter() );
202
203 global $wp_rewrite;
204 $newrules = array();
205
206 $languages = $this->model->get_languages_list( array( 'fields' => 'slug' ) );
207 if ( $this->options['hide_default'] ) {
208 $languages = array_diff( $languages, array( $this->options['default_lang'] ) );
209 }
210
211 if ( ! empty( $languages ) ) {
212 $slug = $wp_rewrite->root . ( $this->options['rewrite'] ? '' : 'language/' ) . '(' . implode( '|', $languages ) . ')/';
213 }
214
215 // For custom post type archives
216 $cpts = array_intersect( $this->model->get_translated_post_types(), get_post_types( array( '_builtin' => false ) ) );
217 $cpts = $cpts ? '#post_type=(' . implode( '|', $cpts ) . ')#' : '';
218
219 foreach ( $rules as $key => $rule ) {
220 // Special case for translated post types and taxonomies to allow canonical redirection
221 if ( $this->options['force_lang'] && in_array( $filter, array_merge( $this->model->get_translated_post_types(), $this->model->get_translated_taxonomies() ) ) ) {
222
223 /**
224 * Filters the rewrite rules to modify
225 *
226 * @since 1.9.1
227 *
228 * @param bool $modify whether to modify or not the rule, defaults to true
229 * @param array $rule original rewrite rule
230 * @param string $filter current set of rules being modified
231 * @param string|bool $archive custom post post type archive name or false if it is not a cpt archive
232 */
233 if ( isset( $slug ) && apply_filters( 'pll_modify_rewrite_rule', true, array( $key => $rule ), $filter, false ) ) {
234 $newrules[ $slug . str_replace( $wp_rewrite->root, '', ltrim( $key, '^' ) ) ] = str_replace(
235 array( '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '[1]', '?' ),
236 array( '[9]', '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '?lang=$matches[1]&' ),
237 $rule
238 ); // Should be enough!
239 }
240
241 $newrules[ $key ] = $rule;
242 }
243
244 // Rewrite rules filtered by language
245 elseif ( in_array( $filter, $this->always_rewrite ) || in_array( $filter, $this->model->get_filtered_taxonomies() ) || ( $cpts && preg_match( $cpts, $rule, $matches ) && ! strpos( $rule, 'name=' ) ) || ( 'rewrite_rules_array' != $filter && $this->options['force_lang'] ) ) {
246
247 /** This filter is documented in include/links-directory.php */
248 if ( apply_filters( 'pll_modify_rewrite_rule', true, array( $key => $rule ), $filter, empty( $matches[1] ) ? false : $matches[1] ) ) {
249 if ( isset( $slug ) ) {
250 $newrules[ $slug . str_replace( $wp_rewrite->root, '', ltrim( $key, '^' ) ) ] = str_replace(
251 array( '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '[1]', '?' ),
252 array( '[9]', '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '?lang=$matches[1]&' ),
253 $rule
254 ); // Should be enough!
255 }
256
257 if ( $this->options['hide_default'] ) {
258 $newrules[ $key ] = str_replace( '?', '?lang=' . $this->options['default_lang'] . '&', $rule );
259 }
260 } else {
261 $newrules[ $key ] = $rule;
262 }
263 }
264
265 // Unmodified rules
266 else {
267 $newrules[ $key ] = $rule;
268 }
269 }
270
271 // The home rewrite rule
272 if ( 'root' == $filter && isset( $slug ) ) {
273 $newrules[ $slug . '?$' ] = $wp_rewrite->index . '?lang=$matches[1]';
274 }
275
276 return $newrules;
277 }
278 }
279