/**
  * Updates the trasher setting of the post with the given ID as well as all related posts.
  *
  * @since   3.0.0
  * @wp-hook save_post
  *
  * @param int     $post_id Post ID.
  * @param WP_post $post    Post object.
  *
  * @return int The number of posts updated.
  */
 public function update_settings($post_id, WP_Post $post)
 {
     if (!$this->nonce->is_valid()) {
         return 0;
     }
     if (!in_array($post->post_status, ['publish', 'draft'], true)) {
         return 0;
     }
     $value = array_key_exists(TrasherSettingRepository::META_KEY, $_POST) ? (bool) $_POST[TrasherSettingRepository::META_KEY] : false;
     if (!$this->setting_repository->update($post_id, $value)) {
         return 0;
     }
     $current_site_id = get_current_blog_id();
     $related_posts = $this->content_relations->get_relations($current_site_id, $post_id, 'post');
     unset($related_posts[$current_site_id]);
     if (!$related_posts) {
         return 1;
     }
     $updated_posts = 1;
     array_walk($related_posts, function ($post_id, $site_id) use(&$updated_posts, $value) {
         switch_to_blog($site_id);
         $updated_posts += $this->setting_repository->update($post_id, $value);
         restore_current_blog();
     });
     return $updated_posts;
 }
 /**
  * Return the relation ID for the given blog ID and term taxonomy ID.
  *
  * @param int $site_id          Blog ID.
  * @param int $term_taxonomy_id Term taxonomy ID.
  *
  * @return string
  */
 public function get_relation_id($site_id, $term_taxonomy_id)
 {
     $translation_ids = $this->content_relations->get_existing_translation_ids($site_id, 0, $term_taxonomy_id, 0, 'term');
     if (!$translation_ids) {
         return '';
     }
     $relation = reset($translation_ids);
     return $relation['ml_source_blogid'] . '-' . $relation['ml_source_elementid'];
 }
 /**
  * Sets up content relations between the source site and the new site.
  *
  * @param int $source_site_id      The ID of the source site.
  * @param int $destination_site_id The ID of the new site.
  *
  * @return void
  */
 private function handle_content_relations($source_site_id, $destination_site_id)
 {
     if ($this->content_relations->has_site_relations($source_site_id)) {
         $this->content_relations->duplicate_relations($source_site_id, $destination_site_id);
         return;
     }
     $this->content_relations->relate_all_posts($source_site_id, $destination_site_id);
     $this->content_relations->relate_all_terms($source_site_id, $destination_site_id);
 }
 /**
  * Disconnects the current post with the one given in the request.
  *
  * @return void
  */
 private function disconnect_post()
 {
     $remote_site_id = $this->context->remote_site_id();
     $remote_post_id = $this->context->remote_post_id();
     $source_site_id = $this->context->source_site_id();
     $translation_ids = $this->content_relations->get_translation_ids($this->context->source_site_id(), $remote_site_id, $this->context->source_post_id(), $remote_post_id, 'post');
     if ($translation_ids['ml_source_blogid'] !== $source_site_id) {
         $remote_site_id = $source_site_id;
         if (0 !== $remote_post_id) {
             $remote_post_id = $this->context->source_post_id();
         }
     }
     $this->content_relations->delete_relation($translation_ids['ml_source_blogid'], $remote_site_id, $translation_ids['ml_source_elementid'], $remote_post_id, 'post');
 }
 /**
  * Trashes all related posts.
  *
  * @since   3.0.0
  * @wp-hook wp_trash_post
  *
  * @param int $post_id Post ID.
  *
  * @return int The number of related posts trashed.
  */
 public function trash_related_posts($post_id)
 {
     if (!$this->setting_repository->get($post_id)) {
         return 0;
     }
     $current_site_id = get_current_blog_id();
     $related_posts = $this->content_relations->get_relations($current_site_id, $post_id, 'post');
     unset($related_posts[$current_site_id]);
     if (!$related_posts) {
         return 0;
     }
     $trashed_post = 0;
     // Temporarily remove the function to avoid recursion.
     $action = current_action();
     remove_action($action, [$this, __FUNCTION__]);
     array_walk($related_posts, function ($post_id, $site_id) use(&$trashed_post) {
         switch_to_blog($site_id);
         $trashed_post += (bool) wp_trash_post($post_id);
         restore_current_blog();
     });
     // Add the function back again.
     add_action($action, [$this, __FUNCTION__]);
     return $trashed_post;
 }
 /**
  * @param array $existing
  * @param int   $source_term_taxonomy_id
  * @param int   $target_site_id
  * @param int   $target_term_taxonomy_id
  *
  * @return bool
  */
 private function update_terms(array $existing, $source_term_taxonomy_id, $target_site_id, $target_term_taxonomy_id)
 {
     // There's nothing to do here
     if (-1 === $target_term_taxonomy_id) {
         return TRUE;
     }
     if (isset($existing[$target_site_id]) && $existing[$target_site_id] === $target_term_taxonomy_id) {
         return TRUE;
     }
     $translation_ids = $this->content_relations->get_translation_ids($this->current_site_id, $target_site_id, $source_term_taxonomy_id, $target_term_taxonomy_id, 'term');
     if ($translation_ids['ml_source_blogid'] !== $this->current_site_id) {
         $target_site_id = $this->current_site_id;
         if (0 !== $target_term_taxonomy_id) {
             $target_term_taxonomy_id = $source_term_taxonomy_id;
         }
     }
     // Delete a relation
     if (0 === $target_term_taxonomy_id) {
         return $this->content_relations->delete_relation($translation_ids['ml_source_blogid'], $target_site_id, $translation_ids['ml_source_elementid'], 0, 'term');
     }
     return $this->content_relations->set_relation($translation_ids['ml_source_blogid'], $target_site_id, $translation_ids['ml_source_elementid'], $target_term_taxonomy_id, 'term');
 }
 /**
  * set the source id of the element
  *
  * @param   int $source_content_id ID of current element
  * @param   int $remote_site_id    ID of remote site
  * @param   int $remote_content_id ID of remote content
  *
  * @return  void
  */
 public function set_linked_element($source_content_id, $remote_site_id, $remote_content_id)
 {
     $this->content_relations->set_relation($this->source_site_id, $remote_site_id, $source_content_id, $remote_content_id, 'post');
 }
 /**
  * Ask for specific translations with arguments.
  *
  *
  * @see prepare_translation_arguments()
  *
  * @param array $args {
  *
  *     Optional. If left out, some magic happens.
  *
  *     @type int    $site_id       Base site
  *     @type int    $content_id    post or term_taxonomy ID, *not* term ID
  *     @type string $type          @see Mlp_Language_Api::get_request_type()
  *     @type bool   $strict        When TRUE (default) only matching exact
  *                                 translations will be included
  *     @type string $search_term   If you want to translate a search
  *     @type string $post_type     For post type archives
  *     @type bool   $include_base  Include the base site in returned list
  *
  * }
  * @return Translation[] Array of Mlp_Translation instances, site IDs are the keys
  */
 public function get_translations(array $args = [])
 {
     $arguments = $this->prepare_translation_arguments($args);
     $key = md5(serialize($arguments));
     $cached = wp_cache_get($key, 'mlp');
     if (is_array($cached)) {
         return $cached;
     }
     $sites = $this->site_relations->get_related_site_ids($arguments['site_id'], $arguments['include_base']);
     if (empty($sites)) {
         return [];
     }
     $content_relations = [];
     if (!empty($arguments['content_id'])) {
         // array with site_ids as keys, content_ids as values
         $content_relations = $this->content_relations->get_relations($arguments['site_id'], $arguments['content_id'], $arguments['type']);
         if (empty($content_relations) && $arguments['strict']) {
             return [];
         }
     }
     $translations = [];
     $languages = $this->get_all_language_data();
     foreach ($sites as $site_id) {
         if (!isset($languages[$site_id])) {
             continue;
         }
         $translations[$site_id] = ['remote_title' => '', 'source_site_id' => $arguments['site_id'], 'target_site_id' => $site_id, 'target_content_id' => 0, 'type' => $arguments['type']];
     }
     reset($translations);
     /** @type WP_Rewrite $wp_rewrite */
     global $wp_rewrite;
     foreach ($translations as $site_id => &$arr) {
         $valid = TRUE;
         if (!empty($content_relations[$site_id])) {
             $content_id = $content_relations[$site_id];
             $arr['target_content_id'] = $content_id;
             if ('term' === $arguments['type']) {
                 $term_translation = new Mlp_Term_Translation($this->wpdb, $wp_rewrite, $this->type_factory);
                 $translation = $term_translation->get_translation($content_id, $site_id);
                 if (!$translation) {
                     $valid = FALSE;
                 } else {
                     $arr = array_merge($arr, $translation);
                 }
             } elseif ('post' === $arguments['type']) {
                 switch_to_blog($site_id);
                 $translation = $this->get_post_translation($content_relations[$site_id], $arguments['strict']);
                 if (!$translation) {
                     $valid = FALSE;
                 } else {
                     $arr = array_merge($arr, $translation);
                 }
                 restore_current_blog();
             }
         } else {
             switch_to_blog($site_id);
             if ('search' === $arguments['type']) {
                 $arr['remote_url'] = $this->type_factory->create_url([get_search_link($arguments['search_term'])]);
             } elseif ('post_type_archive' === $arguments['type'] && !empty($arguments['post_type'])) {
                 $translation = $this->get_post_type_archive_translation($arguments['post_type']);
                 $arr = array_merge($arr, $translation);
             }
             // Nothing found, use fallback if allowed
             if (empty($arr['remote_url']) && !$arguments['strict'] || 'front_page' === $arguments['type']) {
                 $arr['remote_url'] = $this->type_factory->create_url([get_site_url($site_id, '/')]);
             }
             if (empty($arr['remote_url'])) {
                 $valid = FALSE;
             }
             restore_current_blog();
         }
         if (!$valid) {
             unset($translations[$site_id]);
             continue;
         }
         $data = $languages[$site_id];
         if (!isset($data['http_name'])) {
             if (isset($data['lang'])) {
                 $data['http_name'] = $data['lang'];
             } else {
                 $data['http_name'] = '';
             }
         }
         if ('' !== $data['http_name']) {
             $arr['icon_url'] = \Inpsyde\MultilingualPress\get_flag_url_for_site($site_id);
         } else {
             $arr['icon_url'] = $this->type_factory->create_url(['']);
         }
         $arr['suppress_filters'] = $arguments['suppress_filters'];
         $arr = $this->type_factory->create_translation([$arr, $this->type_factory->create_language([$data])]);
     }
     /**
      * Filter the translations before they are used.
      *
      * @param Translation[] $translations Translations.
      * @param array         $arguments    Translation arguments.
      */
     $translations = apply_filters('mlp_translations', $translations, $arguments);
     wp_cache_set($key, $translations, 'mlp');
     // TODO: In deprecated class, add "target_*" aliases for elements in $translations with "remote_*" keys.
     return $translations;
 }