PluginProbe
Polylang / 3.6.7
Polylang v3.6.7
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.6.7, at include/translated-term.php

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