PluginProbe
Polylang / 3.3
Polylang v3.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 / include / crud-terms.php

crud-terms.php in Polylang 3.3, at include/crud-terms.php

330 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 * Adds actions and filters related to languages when creating, reading, updating or deleting posts
8 * Acts both on frontend and backend
9 *
10 * @since 2.4
11 */
12 class PLL_CRUD_Terms {
13 /**
14 * @var PLL_Model
15 */
16 public $model;
17
18 /**
19 * Current language (used to filter the content).
20 *
21 * @var PLL_Language|null
22 */
23 public $curlang;
24
25 /**
26 * Language selected in the admin language filter.
27 *
28 * @var PLL_Language|null
29 */
30 public $filter_lang;
31
32 /**
33 * Preferred language to assign to new contents.
34 *
35 * @var PLL_Language|null
36 */
37 public $pref_lang;
38
39 /**
40 * Stores the 'lang' query var from WP_Query.
41 *
42 * @var string|null
43 */
44 private $tax_query_lang;
45
46 /**
47 * Stores the term name before creating a slug if needed.
48 *
49 * @var string
50 */
51 private $pre_term_name = '';
52
53 /**
54 * Constructor
55 *
56 * @since 2.4
57 *
58 * @param object $polylang
59 */
60 public function __construct( &$polylang ) {
61 $this->model = &$polylang->model;
62 $this->curlang = &$polylang->curlang;
63 $this->filter_lang = &$polylang->filter_lang;
64 $this->pref_lang = &$polylang->pref_lang;
65
66 // Saving terms
67 add_action( 'create_term', array( $this, 'save_term' ), 999, 3 );
68 add_action( 'edit_term', array( $this, 'save_term' ), 999, 3 ); // After PLL_Admin_Filters_Term
69 add_filter( 'pre_term_name', array( $this, 'set_pre_term_name' ) );
70 add_filter( 'pre_term_slug', array( $this, 'set_pre_term_slug' ), 10, 2 );
71
72 // Adds cache domain when querying terms
73 add_filter( 'get_terms_args', array( $this, 'get_terms_args' ), 10, 2 );
74
75 // Filters terms by language
76 add_filter( 'terms_clauses', array( $this, 'terms_clauses' ), 10, 3 );
77 add_action( 'pre_get_posts', array( $this, 'set_tax_query_lang' ), 999 );
78 add_action( 'posts_selection', array( $this, 'unset_tax_query_lang' ), 0 );
79
80 // Deleting terms
81 add_action( 'pre_delete_term', array( $this, 'delete_term' ) );
82 }
83
84 /**
85 * Allows to set a language by default for terms if it has no language yet
86 *
87 * @since 1.5.4
88 *
89 * @param int $term_id
90 * @param string $taxonomy
91 * @return void
92 */
93 protected function set_default_language( $term_id, $taxonomy ) {
94 if ( ! $this->model->term->get_language( $term_id ) ) {
95 if ( ! isset( $this->pref_lang ) && ! empty( $_REQUEST['lang'] ) && $lang = $this->model->get_language( sanitize_key( $_REQUEST['lang'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
96 // Testing $this->pref_lang makes this test pass only on frontend.
97 $this->model->term->set_language( $term_id, $lang );
98 } elseif ( ( $term = get_term( $term_id, $taxonomy ) ) && ! empty( $term->parent ) && $parent_lang = $this->model->term->get_language( $term->parent ) ) {
99 // Sets language from term parent if exists thanks to Scott Kingsley Clark
100 $this->model->term->set_language( $term_id, $parent_lang );
101 } elseif ( isset( $this->pref_lang ) ) {
102 // Always defined on admin, never defined on frontend
103 $this->model->term->set_language( $term_id, $this->pref_lang );
104 } else {
105 // Only on frontend due to the previous test always true on admin
106 $this->model->term->set_language( $term_id, $this->curlang );
107 }
108 }
109 }
110
111 /**
112 * Called when a category or post tag is created or edited.
113 * Does nothing except on taxonomies which are filterable.
114 *
115 * @since 0.1
116 *
117 * @param int $term_id Term id of the term being saved.
118 * @param int $tt_id Term taxonomy id.
119 * @param string $taxonomy Taxonomy name.
120 * @return void
121 */
122 public function save_term( $term_id, $tt_id, $taxonomy ) {
123 if ( $this->model->is_translated_taxonomy( $taxonomy ) ) {
124
125 $lang = $this->model->term->get_language( $term_id );
126
127 if ( empty( $lang ) ) {
128 $this->set_default_language( $term_id, $taxonomy );
129 }
130
131 /**
132 * Fires after the term language and translations are saved.
133 *
134 * @since 1.2
135 *
136 * @param int $term_id Term id.
137 * @param string $taxonomy Taxonomy name.
138 * @param int[] $translations The list of translations term ids.
139 */
140 do_action( 'pll_save_term', $term_id, $taxonomy, $this->model->term->get_translations( $term_id ) );
141 }
142 }
143
144 /**
145 * Get the language(s) to filter WP_Term_Query.
146 *
147 * @since 1.7.6
148 *
149 * @param string[] $taxonomies Queried taxonomies.
150 * @param array $args WP_Term_Query arguments.
151 * @return PLL_Language|string|false The language(s) to use in the filter, false otherwise.
152 */
153 protected function get_queried_language( $taxonomies, $args ) {
154 global $pagenow;
155
156 // Does nothing except on taxonomies which are filterable
157 // Since WP 4.7, make sure not to filter wp_get_object_terms()
158 if ( ! $this->model->is_translated_taxonomy( $taxonomies ) || ! empty( $args['object_ids'] ) ) {
159 return false;
160 }
161
162 // If get_terms is queried with a 'lang' parameter
163 if ( isset( $args['lang'] ) ) {
164 return $args['lang'];
165 }
166
167 // On tags page, everything should be filtered according to the admin language filter except the parent dropdown
168 if ( 'edit-tags.php' === $pagenow && empty( $args['class'] ) ) {
169 return $this->filter_lang;
170 }
171
172 return $this->curlang;
173 }
174
175 /**
176 * Adds language dependent cache domain when querying terms.
177 * Useful as the 'lang' parameter is not included in cache key by WordPress.
178 *
179 * @since 1.3
180 *
181 * @param array $args WP_Term_Query arguments.
182 * @param string[] $taxonomies Queried taxonomies.
183 * @return array Modified arguments.
184 */
185 public function get_terms_args( $args, $taxonomies ) {
186 // Don't break _get_term_hierarchy().
187 if ( 'all' === $args['get'] && 'id' === $args['orderby'] && 'id=>parent' === $args['fields'] ) {
188 $args['lang'] = '';
189 }
190
191 if ( isset( $this->tax_query_lang ) ) {
192 $args['lang'] = empty( $this->tax_query_lang ) && ! empty( $this->curlang ) && ! empty( $args['slug'] ) ? $this->curlang->slug : $this->tax_query_lang;
193 }
194
195 if ( $lang = $this->get_queried_language( $taxonomies, $args ) ) {
196 $lang = is_string( $lang ) && strpos( $lang, ',' ) ? explode( ',', $lang ) : $lang;
197 $key = '_' . ( is_array( $lang ) ? implode( ',', $lang ) : $this->model->get_language( $lang )->slug );
198 $args['cache_domain'] = empty( $args['cache_domain'] ) ? 'pll' . $key : $args['cache_domain'] . $key;
199 }
200 return $args;
201 }
202
203 /**
204 * Filters categories and post tags by language(s) when needed on admin side
205 *
206 * @since 0.2
207 *
208 * @param string[] $clauses List of sql clauses.
209 * @param string[] $taxonomies List of taxonomies.
210 * @param array $args WP_Term_Query arguments.
211 * @return string[] Modified sql clauses.
212 */
213 public function terms_clauses( $clauses, $taxonomies, $args ) {
214 $lang = $this->get_queried_language( $taxonomies, $args );
215 return $this->model->terms_clauses( $clauses, $lang );
216 }
217
218 /**
219 * Sets the WP_Term_Query language when doing a WP_Query.
220 * Needed since WP 4.9.
221 *
222 * @since 2.3.2
223 *
224 * @param WP_Query $query WP_Query object.
225 * @return void
226 */
227 public function set_tax_query_lang( $query ) {
228 $this->tax_query_lang = isset( $query->query_vars['lang'] ) ? $query->query_vars['lang'] : '';
229 }
230
231 /**
232 * Removes the WP_Term_Query language filter for WP_Query.
233 * Needed since WP 4.9.
234 *
235 * @since 2.3.2
236 *
237 * @return void
238 */
239 public function unset_tax_query_lang() {
240 unset( $this->tax_query_lang );
241 }
242
243 /**
244 * Called when a category or post tag is deleted
245 * Deletes language and translations
246 *
247 * @since 0.1
248 *
249 * @param int $term_id
250 * @return void
251 */
252 public function delete_term( $term_id ) {
253 $this->model->term->delete_translation( $term_id );
254 $this->model->term->delete_language( $term_id );
255 }
256
257 /**
258 * Stores the term name for use in pre_term_slug
259 *
260 * @since 0.9.5
261 *
262 * @param string $name term name
263 * @return string unmodified term name
264 */
265 public function set_pre_term_name( $name ) {
266 return $this->pre_term_name = $name;
267 }
268
269 /**
270 * Appends language slug to the term slug if needed.
271 *
272 * @since 3.3
273 *
274 * @param string $slug Term slug.
275 * @param string $taxonomy Term taxonomy.
276 * @return string Slug with a language suffix if found.
277 */
278 public function set_pre_term_slug( $slug, $taxonomy ) {
279 if ( ! $this->model->is_translated_taxonomy( $taxonomy ) ) {
280 return $slug;
281 }
282
283 if ( ! $slug ) {
284 $slug = sanitize_title( $this->pre_term_name );
285 }
286
287 if ( ! term_exists( $slug, $taxonomy ) ) {
288 return $slug;
289 }
290
291 /**
292 * Filters the subsequently inserted term language.
293 *
294 * @since 3.3
295 *
296 * @param PLL_Language|null $lang Found language object, null otherwise.
297 * @param string $taxonomy Term taonomy.
298 * @param string $slug Term slug
299 */
300 $lang = apply_filters( 'pll_inserted_term_language', null, $taxonomy, $slug );
301
302 if ( ! $lang instanceof PLL_Language ) {
303 return $slug;
304 }
305
306 $parent = 0;
307 if ( is_taxonomy_hierarchical( $taxonomy ) ) {
308 /**
309 * Filters the subsequently inserted term parent.
310 *
311 * @since 3.3
312 *
313 * @param int $parent Parent term ID, 0 if none.
314 * @param string $taxonomy Term taxonomy.
315 * @param string $slug Term slug
316 */
317 $parent = apply_filters( 'pll_inserted_term_parent', 0, $taxonomy, $slug );
318 }
319
320 $term_id = (int) $this->model->term_exists_by_slug( $slug, $lang, $taxonomy, $parent );
321
322 // If no term exist in the given language with that slug, it can be created.
323 if ( ! $term_id ) {
324 $slug .= '-' . $lang->slug;
325 }
326
327 return $slug;
328 }
329 }
330