| @@ -1,8 +1,5 @@ | ||
| 1 | 1 | <?php |
| 2 | -/** | |
| 3 | - * @package Polylang | |
| 4 | - */ | |
| 5 | 2 | |
| 6 | 3 | /** |
| 7 | 4 | * Setups the objects languages and translations model |
| 8 | 5 | * |
| @@ -9,9 +6,9 @@ | ||
| 9 | 6 | * @since 1.8 |
| 10 | 7 | */ |
| 11 | 8 | abstract class PLL_Translated_Object { |
| 12 | 9 | public $model; |
| 13 | - protected $object_type, $type, $tax_language, $tax_translations, $tax_tt; | |
| 10 | + protected $object_type, $tax_language, $tax_translations, $tax_tt; | |
| 14 | 11 | |
| 15 | 12 | /** |
| 16 | 13 | * Constructor |
| 17 | 14 | * |
| @@ -40,18 +37,13 @@ | ||
| 40 | 37 | * @param string $taxonomy Polylang taxonomy depending if we are looking for a post ( or term ) language ( or translation ) |
| 41 | 38 | * @return bool|object the term associated to the object in the requested taxonomy if exists, false otherwise |
| 42 | 39 | */ |
| 43 | 40 | public function get_object_term( $object_id, $taxonomy ) { |
| 44 | - if ( empty( $object_id ) || is_wp_error( $object_id ) ) { | |
| 41 | + if ( empty( $object_id ) ) { | |
| 45 | 42 | return false; |
| 46 | 43 | } |
| 47 | 44 | |
| 48 | 45 | $object_id = (int) $object_id; |
| 49 | - | |
| 50 | - if ( $object_id < 0 ) { | |
| 51 | - return false; | |
| 52 | - } | |
| 53 | - | |
| 54 | 46 | $term = get_object_term_cache( $object_id, $taxonomy ); |
| 55 | 47 | |
| 56 | 48 | if ( false === $term ) { |
| 57 | 49 | // query language and translations at the same time |
| @@ -57,9 +49,8 @@ | ||
| 57 | 49 | // query language and translations at the same time |
| 58 | 50 | $taxonomies = array( $this->tax_language, $this->tax_translations ); |
| 59 | 51 | |
| 60 | 52 | // query terms |
| 61 | - $terms = array(); | |
| 62 | 53 | foreach ( wp_get_object_terms( $object_id, $taxonomies, array( 'update_term_meta_cache' => false ) ) as $t ) { |
| 63 | 54 | $terms[ $t->taxonomy ] = $t; |
| 64 | 55 | if ( $t->taxonomy == $taxonomy ) { |
| 65 | 56 | $term = $t; |
| @@ -79,19 +70,16 @@ | ||
| 79 | 70 | return empty( $term ) ? false : $term; |
| 80 | 71 | } |
| 81 | 72 | |
| 82 | 73 | /** |
| 83 | - * Tells whether a translation term must be updated | |
| 74 | + * Tells wether to store a translation term | |
| 84 | 75 | * |
| 85 | - * @since 2.3 | |
| 76 | + * @since 1.8 | |
| 86 | 77 | * |
| 87 | - * @param array $id Post id or term id | |
| 88 | - * @param array $translations An associative array of translations with language code as key and translation id as value | |
| 78 | + * @param array $translations an associative array of translations with language code as key and translation id as value | |
| 89 | 79 | */ |
| 90 | - protected function should_update_translation_group( $id, $translations ) { | |
| 91 | - // Don't do anything if no translations have been added to the group | |
| 92 | - $old_translations = $this->get_translations( $id ); // Includes at least $id itself | |
| 93 | - return count( array_diff_assoc( $translations, $old_translations ) ) > 0; | |
| 80 | + protected function keep_translation_group( $translations ) { | |
| 81 | + return count( $translations ) > 1; | |
| 94 | 82 | } |
| 95 | 83 | |
| 96 | 84 | /** |
| 97 | 85 | * Saves translations for posts or terms |
| @@ -97,10 +85,10 @@ | ||
| 97 | 85 | * Saves translations for posts or terms |
| 98 | 86 | * |
| 99 | 87 | * @since 0.5 |
| 100 | 88 | * |
| 101 | - * @param int $id Post id or term id | |
| 102 | - * @param array $translations An associative array of translations with language code as key and translation id as value | |
| 89 | + * @param int $id post id or term id | |
| 90 | + * @param array $translations an associative array of translations with language code as key and translation id as value | |
| 103 | 91 | */ |
| 104 | 92 | public function save_translations( $id, $translations ) { |
| 105 | 93 | $id = (int) $id; |
| 106 | 94 | |
| @@ -116,23 +104,24 @@ | ||
| 116 | 104 | foreach ( array_diff_assoc( $old_translations, $translations ) as $object_id ) { |
| 117 | 105 | $this->delete_translation( $object_id ); |
| 118 | 106 | } |
| 119 | 107 | |
| 120 | - // Check id we need to create or update the translation group | |
| 121 | - if ( $this->should_update_translation_group( $id, $translations ) ) { | |
| 108 | + // don't create a translation group for untranslated posts as it is useless | |
| 109 | + // but we need one for terms to allow relationships remap when importing from a WXR file | |
| 110 | + if ( $this->keep_translation_group( $translations ) ) { | |
| 122 | 111 | $terms = wp_get_object_terms( $translations, $this->tax_translations ); |
| 123 | 112 | $term = reset( $terms ); |
| 124 | 113 | |
| 125 | 114 | // create a new term if necessary |
| 126 | 115 | if ( empty( $term ) ) { |
| 127 | - wp_insert_term( $group = uniqid( 'pll_' ), $this->tax_translations, array( 'description' => maybe_serialize( $translations ) ) ); | |
| 116 | + wp_insert_term( $group = uniqid( 'pll_' ), $this->tax_translations, array( 'description' => serialize( $translations ) ) ); | |
| 128 | 117 | } |
| 129 | 118 | else { |
| 130 | 119 | // take care not to overwrite extra data stored in description field, if any |
| 131 | - $d = maybe_unserialize( $term->description ); | |
| 120 | + $d = unserialize( $term->description ); | |
| 132 | 121 | $d = is_array( $d ) ? array_diff_key( $d, $old_translations ) : array(); // remove old translations |
| 133 | 122 | $d = array_merge( $d, $translations ); // add new one |
| 134 | - wp_update_term( $group = (int) $term->term_id, $this->tax_translations, array( 'description' => maybe_serialize( $d ) ) ); | |
| 123 | + wp_update_term( $group = (int) $term->term_id, $this->tax_translations, array( 'description' => serialize( $d ) ) ); | |
| 135 | 124 | } |
| 136 | 125 | |
| 137 | 126 | // link all translations to the new term |
| 138 | 127 | foreach ( $translations as $p ) { |
| @@ -161,19 +150,18 @@ | ||
| 161 | 150 | $id = (int) $id; |
| 162 | 151 | $term = $this->get_object_term( $id, $this->tax_translations ); |
| 163 | 152 | |
| 164 | 153 | if ( ! empty( $term ) ) { |
| 165 | - $d = maybe_unserialize( $term->description ); | |
| 166 | - if ( is_array( $d ) ) { | |
| 167 | - $slug = array_search( $id, $this->get_translations( $id ) ); // In case some plugin stores the same value with different key. | |
| 168 | - unset( $d[ $slug ] ); | |
| 169 | - } | |
| 154 | + $d = unserialize( $term->description ); | |
| 155 | + $slug = array_search( $id, $this->get_translations( $id ) ); // in case some plugin stores the same value with different key | |
| 156 | + unset( $d[ $slug ] ); | |
| 170 | 157 | |
| 171 | 158 | if ( empty( $d ) ) { |
| 172 | 159 | wp_delete_term( (int) $term->term_id, $this->tax_translations ); |
| 173 | - } else { | |
| 174 | - wp_update_term( (int) $term->term_id, $this->tax_translations, array( 'description' => maybe_serialize( $d ) ) ); | |
| 175 | 160 | } |
| 161 | + else { | |
| 162 | + wp_update_term( (int) $term->term_id, $this->tax_translations, array( 'description' => serialize( $d ) ) ); | |
| 163 | + } | |
| 176 | 164 | } |
| 177 | 165 | } |
| 178 | 166 | |
| 179 | 167 | /** |
| @@ -185,11 +173,11 @@ | ||
| 185 | 173 | * @return array an associative array of translations with language code as key and translation id as value |
| 186 | 174 | */ |
| 187 | 175 | public function get_translations( $id ) { |
| 188 | 176 | $term = $this->get_object_term( $id, $this->tax_translations ); |
| 189 | - $translations = empty( $term ) ? array() : maybe_unserialize( $term->description ); | |
| 177 | + $translations = empty( $term ) ? array() : unserialize( $term->description ); | |
| 190 | 178 | |
| 191 | - // make sure we return only translations ( thus we allow plugins to store other information in the array ) | |
| 179 | + // make sure we return only translations ( thus we allow plugins to store other informations in the array ) | |
| 192 | 180 | if ( is_array( $translations ) ) { |
| 193 | 181 | $translations = array_intersect_key( $translations, array_flip( $this->model->get_languages_list( array( 'fields' => 'slug' ) ) ) ); |
| 194 | 182 | } |
| 195 | 183 | |
| @@ -229,9 +217,8 @@ | ||
| 229 | 217 | * @param int|string|object $lang language ( term_id or slug or object ) |
| 230 | 218 | * @return bool|int the translation post id or term id if exists, otherwise the post id or term id, false if the post has no language |
| 231 | 219 | */ |
| 232 | 220 | public function get( $id, $lang ) { |
| 233 | - $id = (int) $id; | |
| 234 | 221 | $obj_lang = $this->get_language( $id ); // FIXME is this necessary? |
| 235 | 222 | if ( ! $lang || ! $obj_lang ) { |
| 236 | 223 | return false; |
| 237 | 224 | } |
| @@ -244,26 +231,26 @@ | ||
| 244 | 231 | * A where clause to add to sql queries when filtering by language is needed directly in query |
| 245 | 232 | * |
| 246 | 233 | * @since 1.2 |
| 247 | 234 | * |
| 248 | - * @param object|array|string $lang a PLL_Language object or a comma separated list of language slug or an array of language slugs | |
| 235 | + * @param object|array|string $lang a PLL_Language object or a comma separated list of languag slug or an array of language slugs | |
| 249 | 236 | * @return string where clause |
| 250 | 237 | */ |
| 251 | 238 | public function where_clause( $lang ) { |
| 239 | + global $wpdb; | |
| 252 | 240 | $tt_id = $this->tax_tt; |
| 253 | 241 | |
| 254 | 242 | // $lang is an object |
| 255 | 243 | // generally the case if the query is coming from Polylang |
| 256 | 244 | if ( is_object( $lang ) ) { |
| 257 | - return ' AND pll_tr.term_taxonomy_id = ' . absint( $lang->$tt_id ); | |
| 245 | + return $wpdb->prepare( ' AND pll_tr.term_taxonomy_id = %d', $lang->$tt_id ); | |
| 258 | 246 | } |
| 259 | 247 | |
| 260 | 248 | // $lang is a comma separated list of slugs ( or an array of slugs ) |
| 261 | 249 | // generally the case is the query is coming from outside with 'lang' parameter |
| 262 | - $slugs = is_array( $lang ) ? $lang : explode( ',', $lang ); | |
| 263 | - $languages = array(); | |
| 250 | + $slugs = is_array( $lang ) ? $lang : explode( ',', $lang ); | |
| 264 | 251 | foreach ( $slugs as $slug ) { |
| 265 | - $languages[] = absint( $this->model->get_language( $slug )->$tt_id ); | |
| 252 | + $languages[] = (int) $this->model->get_language( $slug )->$tt_id; | |
| 266 | 253 | } |
| 267 | 254 | |
| 268 | 255 | return ' AND pll_tr.term_taxonomy_id IN ( ' . implode( ',', $languages ) . ' )'; |
| 269 | 256 | } |
| @@ -279,61 +266,7 @@ | ||
| 279 | 266 | */ |
| 280 | 267 | public function get_objects_in_language( $lang ) { |
| 281 | 268 | global $wpdb; |
| 282 | 269 | $tt_id = $this->tax_tt; |
| 283 | - | |
| 284 | - $last_changed = wp_cache_get_last_changed( 'terms' ); | |
| 285 | - $cache_key = "polylang:get_objects_in_language:{$lang->$tt_id}:{$last_changed}"; | |
| 286 | - $cache = wp_cache_get( $cache_key, 'terms' ); | |
| 287 | - | |
| 288 | - if ( false === $cache ) { | |
| 289 | - $object_ids = $wpdb->get_col( $wpdb->prepare( "SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $lang->$tt_id ) ); | |
| 290 | - wp_cache_set( $cache_key, $object_ids, 'terms' ); | |
| 291 | - } else { | |
| 292 | - $object_ids = (array) $cache; | |
| 293 | - } | |
| 294 | - | |
| 295 | - if ( ! $object_ids ) { | |
| 296 | - return array(); | |
| 297 | - } | |
| 298 | - | |
| 299 | - return $object_ids; | |
| 300 | - } | |
| 301 | - | |
| 302 | - /** | |
| 303 | - * Check if a user can synchronize translations | |
| 304 | - * | |
| 305 | - * @since 2.6 | |
| 306 | - * | |
| 307 | - * @param int $id Object id | |
| 308 | - * @return bool | |
| 309 | - */ | |
| 310 | - public function current_user_can_synchronize( $id ) { | |
| 311 | - /** | |
| 312 | - * Filters whether a synchronization capability check should take place | |
| 313 | - * | |
| 314 | - * @since 2.6 | |
| 315 | - * | |
| 316 | - * @param $check null to enable the capability check, | |
| 317 | - * true to always allow the synchronization, | |
| 318 | - * false to always disallow the synchronization. | |
| 319 | - * Defaults to true. | |
| 320 | - * @param $id The synchronization source object id | |
| 321 | - */ | |
| 322 | - $check = apply_filters( "pll_pre_current_user_can_synchronize_{$this->type}", true, $id ); | |
| 323 | - if ( null !== $check ) { | |
| 324 | - return $check; | |
| 325 | - } | |
| 326 | - | |
| 327 | - if ( ! current_user_can( "edit_{$this->type}", $id ) ) { | |
| 328 | - return false; | |
| 329 | - } | |
| 330 | - | |
| 331 | - foreach ( $this->get_translations( $id ) as $tr_id ) { | |
| 332 | - if ( $tr_id !== $id && ! current_user_can( "edit_{$this->type}", $tr_id ) ) { | |
| 333 | - return false; | |
| 334 | - } | |
| 335 | - } | |
| 336 | - | |
| 337 | - return true; | |
| 270 | + return $wpdb->get_col( $wpdb->prepare( "SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $lang->$tt_id ) ); | |
| 338 | 271 | } |
| 339 | 272 | } |