PluginProbe
Polylang / 2.7.2
Polylang v2.7.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 2.7.2, at include/links-directory.php

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