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

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

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