PluginProbe
Polylang / 3.8.6
Polylang v3.8.6
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 / src / crud-terms.php

crud-terms.php in Polylang 3.8.6, at src/crud-terms.php

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