PluginProbe
Polylang / 3.5
Polylang v3.5
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.5, at include/crud-terms.php

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