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

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