| @@ -1,5 +1,8 @@ | ||
| 1 | 1 | <?php |
| 2 | +/** | |
| 3 | + * @package Polylang | |
| 4 | + */ | |
| 2 | 5 | |
| 3 | 6 | /** |
| 4 | 7 | * Abstract class to manage the copy and synchronization of metas |
| 5 | 8 | * |
| @@ -5,12 +8,35 @@ | ||
| 5 | 8 | * |
| 6 | 9 | * @since 2.3 |
| 7 | 10 | */ |
| 8 | 11 | abstract class PLL_Sync_Metas { |
| 12 | + /** | |
| 13 | + * @var PLL_Model | |
| 14 | + */ | |
| 9 | 15 | public $model; |
| 10 | - protected $meta_type, $prev_value, $to_copy; | |
| 11 | 16 | |
| 12 | 17 | /** |
| 18 | + * Meta type. Typically 'post' or 'term'. | |
| 19 | + * | |
| 20 | + * @var string | |
| 21 | + */ | |
| 22 | + protected $meta_type; | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * Stores the previous values when updating a meta. | |
| 26 | + * | |
| 27 | + * @var array | |
| 28 | + */ | |
| 29 | + protected $prev_value; | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * Stores the metas to synchronize before deleting them. | |
| 33 | + * | |
| 34 | + * @var array | |
| 35 | + */ | |
| 36 | + protected $to_copy; | |
| 37 | + | |
| 38 | + /** | |
| 13 | 39 | * Constructor |
| 14 | 40 | * |
| 15 | 41 | * @since 2.3 |
| 16 | 42 | * |
| @@ -31,8 +57,10 @@ | ||
| 31 | 57 | /** |
| 32 | 58 | * Removes "added_{$this->meta_type}_meta" action |
| 33 | 59 | * |
| 34 | 60 | * @since 2.3 |
| 61 | + * | |
| 62 | + * @return void | |
| 35 | 63 | */ |
| 36 | 64 | protected function remove_add_meta_action() { |
| 37 | 65 | remove_action( "added_{$this->meta_type}_meta", array( $this, 'add_meta' ), 10, 4 ); |
| 38 | 66 | } |
| @@ -40,8 +68,10 @@ | ||
| 40 | 68 | /** |
| 41 | 69 | * Removes all meta synchronization actions and filters |
| 42 | 70 | * |
| 43 | 71 | * @since 2.3 |
| 72 | + * | |
| 73 | + * @return void | |
| 44 | 74 | */ |
| 45 | 75 | protected function remove_all_meta_actions() { |
| 46 | 76 | $this->remove_add_meta_action(); |
| 47 | 77 | |
| @@ -55,8 +85,10 @@ | ||
| 55 | 85 | /** |
| 56 | 86 | * Adds "added_{$this->meta_type}_meta" action |
| 57 | 87 | * |
| 58 | 88 | * @since 2.3 |
| 89 | + * | |
| 90 | + * @return void | |
| 59 | 91 | */ |
| 60 | 92 | protected function restore_add_meta_action() { |
| 61 | 93 | add_action( "added_{$this->meta_type}_meta", array( $this, 'add_meta' ), 10, 4 ); |
| 62 | 94 | } |
| @@ -64,8 +96,10 @@ | ||
| 64 | 96 | /** |
| 65 | 97 | * Adds meta synchronization actions and filters |
| 66 | 98 | * |
| 67 | 99 | * @since 2.3 |
| 100 | + * | |
| 101 | + * @return void | |
| 68 | 102 | */ |
| 69 | 103 | protected function add_all_meta_actions() { |
| 70 | 104 | $this->restore_add_meta_action(); |
| 71 | 105 | |
| @@ -103,30 +137,30 @@ | ||
| 103 | 137 | return apply_filters( "pll_translate_{$this->meta_type}_meta", maybe_unserialize( $value ), $key, $lang, $from, $to ); |
| 104 | 138 | } |
| 105 | 139 | |
| 106 | 140 | /** |
| 107 | - * Get the custom fields to copy or synchronize | |
| 141 | + * Get the custom fields to copy or synchronize. | |
| 108 | 142 | * |
| 109 | 143 | * @since 2.3 |
| 110 | 144 | * |
| 111 | - * @param int $from Id of the post from which we copy informations | |
| 112 | - * @param int $to Id of the post to which we paste informations | |
| 113 | - * @param string $lang Language slug | |
| 114 | - * @param bool $sync True if it is synchronization, false if it is a copy | |
| 115 | - * @return array List of meta keys | |
| 145 | + * @param int $from Id of the post from which we copy informations. | |
| 146 | + * @param int $to Id of the post to which we paste informations. | |
| 147 | + * @param string $lang Language slug. | |
| 148 | + * @param bool $sync True if it is synchronization, false if it is a copy. | |
| 149 | + * @return string[] List of meta keys. | |
| 116 | 150 | */ |
| 117 | 151 | protected function get_metas_to_copy( $from, $to, $lang, $sync = false ) { |
| 118 | 152 | /** |
| 119 | - * Filter the custom fields to copy or synchronize | |
| 153 | + * Filters the custom fields to copy or synchronize. | |
| 120 | 154 | * |
| 121 | 155 | * @since 0.6 |
| 122 | 156 | * @since 1.9.2 The `$from`, `$to`, `$lang` parameters were added. |
| 123 | 157 | * |
| 124 | - * @param array $keys List of custom fields names | |
| 125 | - * @param bool $sync True if it is synchronization, false if it is a copy | |
| 126 | - * @param int $from Id of the post from which we copy informations | |
| 127 | - * @param int $to Id of the post to which we paste informations | |
| 128 | - * @param string $lang Language slug | |
| 158 | + * @param string[] $keys List of custom fields names. | |
| 159 | + * @param bool $sync True if it is synchronization, false if it is a copy. | |
| 160 | + * @param int $from Id of the post from which we copy informations. | |
| 161 | + * @param int $to Id of the post to which we paste informations. | |
| 162 | + * @param string $lang Language slug. | |
| 129 | 163 | */ |
| 130 | 164 | return array_unique( apply_filters( "pll_copy_{$this->meta_type}_metas", array(), $sync, $from, $to, $lang ) ); |
| 131 | 165 | } |
| 132 | 166 | |
| @@ -164,8 +198,9 @@ | ||
| 164 | 198 | * @param int $mid Meta id. |
| 165 | 199 | * @param int $id Object ID. |
| 166 | 200 | * @param string $meta_key Meta key. |
| 167 | 201 | * @param mixed $meta_value Meta value. Must be serializable if non-scalar. |
| 202 | + * @return void | |
| 168 | 203 | */ |
| 169 | 204 | public function add_meta( $mid, $id, $meta_key, $meta_value ) { |
| 170 | 205 | static $avoid_recursion = false; |
| 171 | 206 | |
| @@ -177,9 +212,9 @@ | ||
| 177 | 212 | if ( $tr_id != $id ) { |
| 178 | 213 | $to_copy = $this->get_metas_to_copy( $id, $tr_id, $lang, true ); |
| 179 | 214 | if ( in_array( $meta_key, $to_copy ) ) { |
| 180 | 215 | $meta_value = $this->maybe_translate_value( $meta_value, $meta_key, $id, $tr_id, $lang ); |
| 181 | - add_metadata( $this->meta_type, $tr_id, $meta_key, is_string( $meta_value ) ? wp_slash( $meta_value ) : $meta_value ); | |
| 216 | + add_metadata( $this->meta_type, $tr_id, wp_slash( $meta_key ), is_object( $meta_value ) ? $meta_value : wp_slash( $meta_value ) ); | |
| 182 | 217 | } |
| 183 | 218 | } |
| 184 | 219 | } |
| 185 | 220 | |
| @@ -215,8 +250,9 @@ | ||
| 215 | 250 | * @param int $mid Meta id. |
| 216 | 251 | * @param int $id Object ID. |
| 217 | 252 | * @param string $meta_key Meta key. |
| 218 | 253 | * @param mixed $meta_value Meta value. Must be serializable if non-scalar. |
| 254 | + * @return void | |
| 219 | 255 | */ |
| 220 | 256 | public function update_meta( $mid, $id, $meta_key, $meta_value ) { |
| 221 | 257 | static $avoid_recursion = false; |
| 222 | 258 | |
| @@ -234,9 +270,9 @@ | ||
| 234 | 270 | if ( $tr_id != $id && in_array( $meta_key, $this->get_metas_to_copy( $id, $tr_id, $lang, true ) ) ) { |
| 235 | 271 | if ( empty( $this->prev_value[ $hash ] ) || $this->prev_value[ $hash ] === $prev_meta->meta_value ) { |
| 236 | 272 | $prev_value = $this->maybe_translate_value( $prev_meta->meta_value, $meta_key, $id, $tr_id, $lang ); |
| 237 | 273 | $meta_value = $this->maybe_translate_value( $meta_value, $meta_key, $id, $tr_id, $lang ); |
| 238 | - update_metadata( $this->meta_type, $tr_id, $meta_key, is_string( $meta_value ) ? wp_slash( $meta_value ) : $meta_value, $prev_value ); | |
| 274 | + update_metadata( $this->meta_type, $tr_id, wp_slash( $meta_key ), is_object( $meta_value ) ? $meta_value : wp_slash( $meta_value ), $prev_value ); | |
| 239 | 275 | } |
| 240 | 276 | } |
| 241 | 277 | } |
| 242 | 278 | $this->restore_add_meta_action(); |
| @@ -247,14 +283,15 @@ | ||
| 247 | 283 | } |
| 248 | 284 | } |
| 249 | 285 | |
| 250 | 286 | /** |
| 251 | - * Store metas to synchronize before deleting them | |
| 287 | + * Store metas to synchronize before deleting them. | |
| 252 | 288 | * |
| 253 | 289 | * @since 2.3 |
| 254 | 290 | * |
| 255 | - * @param array $mids Not used | |
| 291 | + * @param int[] $mids Not used. | |
| 256 | 292 | * @param int $id Object ID. |
| 293 | + * @return void | |
| 257 | 294 | */ |
| 258 | 295 | public function store_metas_to_sync( $mids, $id ) { |
| 259 | 296 | $tr_ids = $this->model->{$this->meta_type}->get_translations( $id ); |
| 260 | 297 | |
| @@ -263,16 +300,17 @@ | ||
| 263 | 300 | } |
| 264 | 301 | } |
| 265 | 302 | |
| 266 | 303 | /** |
| 267 | - * Synchronize deleted meta across translations | |
| 304 | + * Synchronizes deleted meta across translations. | |
| 268 | 305 | * |
| 269 | 306 | * @since 2.3 |
| 270 | 307 | * |
| 271 | - * @param array $mids Not used | |
| 308 | + * @param int[] $mids Not used. | |
| 272 | 309 | * @param int $id Object ID. |
| 273 | 310 | * @param string $key Meta key. |
| 274 | 311 | * @param mixed $value Meta value. |
| 312 | + * @return void | |
| 275 | 313 | */ |
| 276 | 314 | public function delete_meta( $mids, $id, $key, $value ) { |
| 277 | 315 | static $avoid_recursion = false; |
| 278 | 316 | |
| @@ -286,9 +324,9 @@ | ||
| 286 | 324 | if ( in_array( $key, $this->to_copy[ $id ][ $tr_id ] ) ) { |
| 287 | 325 | if ( '' !== $value && null !== $value && false !== $value ) { // Same test as WP |
| 288 | 326 | $value = $this->maybe_translate_value( $value, $key, $id, $tr_id, $lang ); |
| 289 | 327 | } |
| 290 | - delete_metadata( $this->meta_type, $tr_id, $key, is_string( $value ) ? wp_slash( $value ) : $value ); | |
| 328 | + delete_metadata( $this->meta_type, $tr_id, wp_slash( $key ), is_object( $value ) ? $value : wp_slash( $value ) ); | |
| 291 | 329 | } |
| 292 | 330 | } |
| 293 | 331 | } |
| 294 | 332 | } |
| @@ -304,8 +342,9 @@ | ||
| 304 | 342 | * @param int $from Id of the source object |
| 305 | 343 | * @param int $to Id of the target object |
| 306 | 344 | * @param string $lang Language code of the target object |
| 307 | 345 | * @param bool $sync Optional, defaults to true. True if it is synchronization, false if it is a copy |
| 346 | + * @return void | |
| 308 | 347 | */ |
| 309 | 348 | public function copy( $from, $to, $lang, $sync = false ) { |
| 310 | 349 | $this->remove_all_meta_actions(); |
| 311 | 350 | |
| @@ -319,9 +358,9 @@ | ||
| 319 | 358 | foreach ( $to_copy as $key ) { |
| 320 | 359 | if ( empty( $metas[ $key ] ) ) { |
| 321 | 360 | if ( ! empty( $tr_metas[ $key ] ) ) { |
| 322 | 361 | // If the meta key is not present in the source object, delete all values |
| 323 | - delete_metadata( $this->meta_type, $to, $key ); | |
| 362 | + delete_metadata( $this->meta_type, $to, wp_slash( $key ) ); | |
| 324 | 363 | } |
| 325 | 364 | } else { |
| 326 | 365 | if ( ! empty( $tr_metas[ $key ] ) && 1 === count( $metas[ $key ] ) && 1 === count( $tr_metas[ $key ] ) ) { |
| 327 | 366 | // One custom field to update |
| @@ -327,20 +366,20 @@ | ||
| 327 | 366 | // One custom field to update |
| 328 | 367 | $value = reset( $metas[ $key ] ); |
| 329 | 368 | $value = maybe_unserialize( $value ); |
| 330 | 369 | $to_value = $this->maybe_translate_value( $value, $key, $from, $to, $lang ); |
| 331 | - update_metadata( $this->meta_type, $to, $key, is_string( $to_value ) ? wp_slash( $to_value ) : $to_value ); | |
| 370 | + update_metadata( $this->meta_type, $to, wp_slash( $key ), is_object( $to_value ) ? $to_value : wp_slash( $to_value ) ); | |
| 332 | 371 | } else { |
| 333 | 372 | // Multiple custom fields, either in the source or the target |
| 334 | 373 | if ( ! empty( $tr_metas[ $key ] ) ) { |
| 335 | 374 | // The synchronization of multiple values custom fields is easier if we delete all metas first |
| 336 | - delete_metadata( $this->meta_type, $to, $key ); | |
| 375 | + delete_metadata( $this->meta_type, $to, wp_slash( $key ) ); | |
| 337 | 376 | } |
| 338 | 377 | |
| 339 | 378 | foreach ( $metas[ $key ] as $value ) { |
| 340 | 379 | $value = maybe_unserialize( $value ); |
| 341 | 380 | $to_value = $this->maybe_translate_value( $value, $key, $from, $to, $lang ); |
| 342 | - add_metadata( $this->meta_type, $to, $key, is_string( $to_value ) ? wp_slash( $to_value ) : $to_value ); | |
| 381 | + add_metadata( $this->meta_type, $to, wp_slash( $key ), is_object( $to_value ) ? $to_value : wp_slash( $to_value ) ); | |
| 343 | 382 | } |
| 344 | 383 | } |
| 345 | 384 | } |
| 346 | 385 | } |
| @@ -353,11 +392,12 @@ | ||
| 353 | 392 | * that saving a post (or term) will synchronize them. |
| 354 | 393 | * |
| 355 | 394 | * @since 2.3 |
| 356 | 395 | * |
| 357 | - * @param int $object_id Id of the object being asaved | |
| 358 | - * @param object $obj Not used | |
| 359 | - * @param array $translations The list of translations object ids | |
| 396 | + * @param int $object_id Id of the object being saved. | |
| 397 | + * @param object $obj Not used. | |
| 398 | + * @param int[] $translations The list of translations object ids. | |
| 399 | + * @return void | |
| 360 | 400 | */ |
| 361 | 401 | public function save_object( $object_id, $obj, $translations ) { |
| 362 | 402 | foreach ( $translations as $tr_lang => $tr_id ) { |
| 363 | 403 | if ( $tr_id != $object_id ) { |