PluginProbe
Polylang / 3.4
Polylang v3.4
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 / translated-term.php

translated-term.php in Polylang 3.4, at include/translated-term.php

322 lines 8.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 defined( 'ABSPATH' ) || exit;
7
8 /**
9 * Sets the taxonomies languages and translations model up.
10 *
11 * @since 1.8
12 */
13 class PLL_Translated_Term extends PLL_Translated_Object implements PLL_Translatable_Object_With_Types_Interface {
14
15 use PLL_Translatable_Object_With_Types_Trait;
16
17 /**
18 * Taxonomy name for the languages.
19 *
20 * @var string
21 *
22 * @phpstan-var non-empty-string
23 */
24 protected $tax_language = 'term_language';
25
26 /**
27 * Object type to use when registering the taxonomy.
28 *
29 * @var string
30 *
31 * @phpstan-var non-empty-string
32 */
33 protected $object_type = 'term';
34
35 /**
36 * Identifier that must be unique for each type of content.
37 * Also used when checking capabilities.
38 *
39 * @var string
40 *
41 * @phpstan-var non-empty-string
42 */
43 protected $type = 'term';
44
45 /**
46 * Identifier for each type of content to used for cache type.
47 *
48 * @var string
49 *
50 * @phpstan-var non-empty-string
51 */
52 protected $cache_type = 'terms';
53
54
55 /**
56 * Taxonomy name for the translation groups.
57 *
58 * @var string
59 *
60 * @phpstan-var non-empty-string
61 */
62 protected $tax_translations = 'term_translations';
63
64 /**
65 * Constructor.
66 *
67 * @since 1.8
68 *
69 * @param PLL_Model $model Instance of `PLL_Model`.
70 */
71 public function __construct( PLL_Model &$model ) {
72 $this->db = array(
73 'table' => $GLOBALS['wpdb']->term_taxonomy,
74 'id_column' => 'term_id',
75 'type_column' => 'taxonomy',
76 'default_alias' => 't',
77 );
78
79 parent::__construct( $model );
80
81 // Keep hooks in constructor for backward compatibility.
82 $this->init();
83 }
84
85 /**
86 * Adds hooks.
87 *
88 * @since 3.4
89 *
90 * @return static
91 */
92 public function init() {
93 add_filter( 'get_terms', array( $this, '_prime_terms_cache' ), 10, 2 );
94 add_action( 'clean_term_cache', array( $this, 'clean_term_cache' ) );
95 return parent::init();
96 }
97
98 /**
99 * Stores the term's language into the database.
100 *
101 * @since 0.6
102 * @since 3.4 Renamed the parameter $term_id into $id.
103 *
104 * @param int $id Term ID.
105 * @param PLL_Language|string|int $lang Language (object, slug, or term ID).
106 * @return bool True when successfully assigned. False otherwise (or if the given language is already assigned to
107 * the object).
108 */
109 public function set_language( $id, $lang ) {
110 if ( ! parent::set_language( $id, $lang ) ) {
111 return false;
112 }
113
114 $id = $this->sanitize_int_id( $id );
115
116 // Add translation group for correct WXR export.
117 $translations = $this->get_translations( $id );
118
119 if ( ! empty( $translations ) ) {
120 $translations = array_diff( $translations, array( $id ) );
121 }
122
123 $this->save_translations( $id, $translations );
124
125 return true;
126 }
127
128 /**
129 * Returns the language of a term.
130 *
131 * @since 0.1
132 * @since 3.4 Renamed the parameter $value into $id.
133 * @since 3.4 Deprecated to retrieve the language by term slug + taxonomy anymore.
134 *
135 * @param int $id Term ID.
136 * @return PLL_Language|false A `PLL_Language` object. `false` if no language is associated to that term or if the
137 * ID is invalid.
138 */
139 public function get_language( $id ) {
140 if ( func_num_args() > 1 ) {
141 // Backward compatibility.
142 _deprecated_argument( __METHOD__ . '()', '3.4' );
143
144 $term = get_term_by( 'slug', $id, func_get_arg( 1 ) ); // @phpstan-ignore-line
145 $id = $term instanceof WP_Term ? $term->term_id : 0;
146 }
147
148 return parent::get_language( $id );
149 }
150
151 /**
152 * Deletes a translation of a term.
153 *
154 * @since 0.5
155 *
156 * @param int $id Term ID.
157 * @return void
158 */
159 public function delete_translation( $id ) {
160 global $wpdb;
161
162 $id = $this->sanitize_int_id( $id );
163
164 if ( empty( $id ) ) {
165 return;
166 }
167
168 $slug = array_search( $id, $this->get_translations( $id ) ); // In case some plugin stores the same value with different key.
169
170 parent::delete_translation( $id );
171 wp_delete_object_term_relationships( $id, $this->tax_translations );
172
173 if ( doing_action( 'pre_delete_term' ) ) {
174 return;
175 }
176
177 if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( * ) FROM $wpdb->terms WHERE term_id = %d;", $id ) ) ) {
178 return;
179 }
180
181 // Always keep a group for terms to allow relationships remap when importing from a WXR file.
182 $group = uniqid( 'pll_' );
183 $translations = array( $slug => $id );
184 wp_insert_term( $group, $this->tax_translations, array( 'description' => maybe_serialize( $translations ) ) );
185 wp_set_object_terms( $id, $group, $this->tax_translations );
186 }
187
188 /**
189 * Returns object types (taxonomy names) that need to be translated.
190 * The taxonomies list is cached for better performance.
191 * The method waits for 'after_setup_theme' to apply the cache to allow themes adding the filter in functions.php.
192 *
193 * @since 3.4
194 *
195 * @param bool $filter True if we should return only valid registered object types.
196 * @return string[] Object type names for which Polylang manages languages.
197 *
198 * @phpstan-return array<non-empty-string, non-empty-string>
199 */
200 public function get_translated_object_types( $filter = true ) {
201 $taxonomies = $this->model->cache->get( 'taxonomies' );
202
203 if ( false === $taxonomies ) {
204 $taxonomies = array( 'category' => 'category', 'post_tag' => 'post_tag' );
205
206 if ( ! empty( $this->model->options['taxonomies'] ) && is_array( $this->model->options['taxonomies'] ) ) {
207 $taxonomies = array_merge( $taxonomies, array_combine( $this->model->options['taxonomies'], $this->model->options['taxonomies'] ) );
208 }
209
210 /**
211 * Filters the list of taxonomies available for translation.
212 * The default are taxonomies which have the parameter ‘public’ set to true.
213 * The filter must be added soon in the WordPress loading process:
214 * in a function hooked to ‘plugins_loaded’ or directly in functions.php for themes.
215 *
216 * @since 0.8
217 *
218 * @param string[] $taxonomies List of taxonomy names (as array keys and values).
219 * @param bool $is_settings True when displaying the list of custom taxonomies in Polylang settings.
220 */
221 $taxonomies = apply_filters( 'pll_get_taxonomies', $taxonomies, false );
222
223 if ( did_action( 'after_setup_theme' ) ) {
224 $this->model->cache->set( 'taxonomies', $taxonomies );
225 }
226 }
227
228 /** @var array<non-empty-string, non-empty-string> $taxonomies */
229 return $filter ? array_intersect( $taxonomies, get_taxonomies() ) : $taxonomies;
230 }
231
232 /**
233 * Caches the language and translations when terms are queried by get_terms().
234 *
235 * @since 1.2
236 *
237 * @param WP_Term[]|int[] $terms Queried terms.
238 * @param string[] $taxonomies Queried taxonomies.
239 * @return WP_Term[]|int[] Unmodified $terms.
240 *
241 * @phpstan-param array<WP_Term|positive-int> $terms
242 * @phpstan-param array<non-empty-string> $taxonomies
243 * @phpstan-return array<WP_Term|positive-int>
244 */
245 public function _prime_terms_cache( $terms, $taxonomies ) {
246 $ids = array();
247
248 if ( is_array( $terms ) && $this->model->is_translated_taxonomy( $taxonomies ) ) {
249 foreach ( $terms as $term ) {
250 $ids[] = is_object( $term ) ? $term->term_id : (int) $term;
251 }
252 }
253
254 if ( ! empty( $ids ) ) {
255 update_object_term_cache( array_unique( $ids ), 'term' ); // Adds language and translation of terms to cache.
256 }
257 return $terms;
258 }
259
260 /**
261 * When the term cache is cleaned, cleans the object term cache too.
262 *
263 * @since 2.0
264 *
265 * @param int[] $ids An array of term IDs.
266 * @return void
267 *
268 * @phpstan-param array<positive-int> $ids
269 */
270 public function clean_term_cache( $ids ) {
271 clean_object_term_cache( $this->sanitize_int_ids_list( $ids ), 'term' );
272 }
273
274 /**
275 * Tells whether a translation term must be updated.
276 *
277 * @since 2.3
278 *
279 * @param int $id Term ID.
280 * @param int[] $translations An associative array of translations with language code as key and translation ID as
281 * value. Make sure to sanitize this.
282 * @return bool
283 *
284 * @phpstan-param array<non-empty-string, positive-int> $translations
285 */
286 protected function should_update_translation_group( $id, $translations ) {
287 // Don't do anything if no translations have been added to the group.
288 $old_translations = $this->get_translations( $id );
289 if ( count( $translations ) > 1 && ! empty( array_diff_assoc( $translations, $old_translations ) ) ) {
290 return true;
291 }
292
293 // But we need a translation group for terms to allow relationships remap when importing from a WXR file
294 $term = $this->get_object_term( $id, $this->tax_translations );
295 return empty( $term ) || ! empty( array_diff_assoc( $translations, $old_translations ) );
296 }
297
298 /**
299 * Assigns a language to terms in mass.
300 *
301 * @since 1.2
302 * @since 3.4 Moved from PLL_Admin_Model class.
303 *
304 * @param int[] $ids Array of post ids or term ids.
305 * @param PLL_Language $lang Language to assign to the posts or terms.
306 * @return void
307 */
308 public function set_language_in_mass( $ids, $lang ) {
309 parent::set_language_in_mass( $ids, $lang );
310
311 $translations = array();
312
313 foreach ( $ids as $id ) {
314 $translations[] = array( $lang->slug => $id );
315 }
316
317 if ( ! empty( $translations ) ) {
318 $this->set_translation_in_mass( $translations );
319 }
320 }
321 }
322