/** @brief Syncs the terms of a taxonomy from the parent blog in the BCD to the current blog. @details If $bcd->add_new_taxonomies is set, new taxonomies will be created, else they are ignored. Upon syncing, the broadcasting data will contain an array of the equivalent source terms <-> child terms in: $bcd->parent_blog_taxonomies[ $taxonomy ][ 'equivalent_terms' ][ $blog_id ] @param broadcasting_data $bcd The broadcasting data. @param string $taxonomy The taxonomy to sync. @since 20131004 **/ public function sync_terms($bcd, $taxonomy) { $source_terms = $bcd->parent_blog_taxonomies[$taxonomy]['terms']; if (!isset($bcd->parent_blog_taxonomies[$taxonomy]['equivalent_terms'])) { $bcd->parent_blog_taxonomies[$taxonomy]['equivalent_terms'] = []; } // Select only those terms that exist in the blog. We select them by slugs. $needed_slugs = []; foreach ($source_terms as $source_term) { $needed_slugs[$source_term->slug] = true; } $target_terms = get_terms($taxonomy, ['slug' => array_keys($needed_slugs), 'hide_empty' => false]); $target_terms = $this->array_rekey($target_terms, 'term_id'); $this->debug('Target terms: %s', $target_terms); $refresh_cache = false; // Keep track of which terms we've found. $found_targets = []; $found_sources = []; // Also keep track of which sources we haven't found on the target blog. $unfound_sources = $source_terms; // Rekey the terms in order to find them faster. $source_slugs = []; foreach ($source_terms as $source_term_id => $source_term) { $source_slugs[$source_term->slug] = $source_term_id; } $target_slugs = []; foreach ($target_terms as $target_term) { $target_slugs[$target_term->slug] = $target_term->term_id; } // Step 1. $this->debug('Find out which of the source terms exist on the target blog.'); foreach ($source_slugs as $source_slug => $source_term_id) { if (!isset($target_slugs[$source_slug])) { continue; } $target_term_id = $target_slugs[$source_slug]; $this->debug('Found source term %s. Source ID: %s. Target ID: %s.', $source_slug, $source_term_id, $target_term_id); $found_targets[$target_term_id] = $source_term_id; $found_sources[$source_term_id] = $target_term_id; unset($unfound_sources[$source_term_id]); } // These sources were not found. Add them. if (isset($bcd->add_new_taxonomies) && $bcd->add_new_taxonomies) { $this->debug('%s taxonomies are missing on this blog.', count($unfound_sources)); foreach ($unfound_sources as $unfound_source_id => $unfound_source) { // We need to clone because we will be modifying the source. $unfound_source = clone $unfound_source; if ($unfound_source->parent > 0) { $this->debug('The unfound source needs a parent.'); $parent_of_equivalent_source_term = $unfound_source->parent; $unfound_source->parent = 0; // Does the parent of the source have an equivalent target? if (isset($found_sources[$parent_of_equivalent_source_term])) { $unfound_source->parent = $found_sources[$parent_of_equivalent_source_term]; } // Recursively insert ancestors if needed, and get the target term's parent's ID if ($unfound_source->parent == 0) { $this->debug('Inserting parent term for %s', $unfound_source->slug); $unfound_source->parent = $this->insert_term_ancestors($unfound_source, $taxonomy, $found_targets, $bcd->parent_blog_taxonomies[$taxonomy]['terms']); } } $action = new actions\wp_insert_term(); $action->taxonomy = $taxonomy; $action->term = $unfound_source; $action->execute(); if ($action->new_term) { $new_term = $action->new_term; $new_term_id = $new_term->term_id; $target_terms[$new_term_id] = $new_term; $found_sources[$unfound_source_id] = $new_term_id; $found_targets[$new_term_id] = $unfound_source_id; $refresh_cache = true; } } } // Now we know which of the terms on our target blog exist on the source blog. // Next step: see if the parents are the same on the target as they are on the source. // "Same" meaning pointing to the same slug. $this->debug('About to update taxonomy terms.'); foreach ($found_targets as $target_term_id => $source_term_id) { $source_term = (object) $source_terms[$source_term_id]; $target_term = (object) $target_terms[$target_term_id]; $action = new actions\wp_update_term(); $action->taxonomy = $taxonomy; // The old term is the target term, since it contains the old values. $action->set_old_term($target_term); // The new term is the source term, since it has the newer data. $action->set_new_term($source_term); // ... but the IDs have to be switched around, since the target term has the new ID. $action->switch_data(); // Does the source term even have a parent? if ($source_term->parent > 0) { $parent_of_equivalent_source_term = $source_term->parent; $this->debug('Parent of equivalent source term: %s', $parent_of_equivalent_source_term); // Does the parent of the source have an equivalent target? if (isset($found_sources[$parent_of_equivalent_source_term])) { $new_parent = $found_sources[$parent_of_equivalent_source_term]; } } else { $new_parent = 0; } $action->switch_data('parent'); $action->new_term->parent = $new_parent; $action->execute(); $refresh_cache |= $action->updated; } // Save the equivalent sources for later use. $blog_id = get_current_blog_id(); $bcd->parent_blog_taxonomies[$taxonomy]['equivalent_terms'][$blog_id] = $found_sources; // wp_update_category alone won't work. The "cache" needs to be cleared. // see: http://wordpress.org/support/topic/category_children-how-to-recalculate?replies=4 if ($refresh_cache) { delete_option('category_children'); } }
/** @brief Broadcast a post. @details The BC data parameter contains all necessary information about what is being broadcasted, to which blogs, options, etc. @param broadcasting_data $broadcasting_data The broadcasting data object. @since 20130603 **/ public function broadcast_post($broadcasting_data) { $bcd = $broadcasting_data; // To prevent recursion array_push($this->broadcasting, $bcd); $this->debug('Broadcast version %s.', THREEWP_BROADCAST_VERSION); $this->debug('Broadcasting the post %s <pre>%s</pre>', $bcd->post->ID, $bcd->post); $this->debug('The POST is <pre>%s</pre>', $bcd->_POST); // See: For nested broadcasts. Just in case. switch_to_blog($bcd->parent_blog_id); if ($bcd->link) { $this->debug('Linking is enabled.'); if ($broadcasting_data->broadcast_data === null) { // Prepare the broadcast data for linked children. $bcd->broadcast_data = $this->get_post_broadcast_data($bcd->parent_blog_id, $bcd->post->ID); // Does this post type have parent support, so that we can link to a parent? if ($bcd->post_type_is_hierarchical && $bcd->post->post_parent > 0) { $parent_broadcast_data = $this->get_post_broadcast_data($bcd->parent_blog_id, $bcd->post->post_parent); } $this->debug('Post type is hierarchical: %s', $this->yes_no($bcd->post_type_is_hierarchical)); } } else { $this->debug('Linking is disabled.'); } if ($bcd->taxonomies) { $this->debug('Will broadcast taxonomies.'); $this->collect_post_type_taxonomies($bcd); $this->debug('Parent taxonomies dump: %s', $bcd->parent_post_taxonomies); } else { $this->debug('Will not broadcast taxonomies.'); } $bcd->attachment_data = []; $attached_files = get_children('post_parent=' . $bcd->post->ID . '&post_type=attachment'); $has_attached_files = count($attached_files) > 0; if ($has_attached_files) { $this->debug('Has %s attachments.', count($attached_files)); foreach ($attached_files as $attached_file) { try { $data = attachment_data::from_attachment_id($attached_file); $data->set_attached_to_parent($bcd->post); $bcd->attachment_data[$attached_file->ID] = $data; $this->debug('Attachment %s found.', $attached_file->ID); } catch (Exception $e) { $this->debug('Exception adding attachment: ' . $e->getMessage()); } } } if ($bcd->custom_fields !== false) { if (!is_object($bcd->custom_fields)) { $bcd->custom_fields = (object) []; } $this->debug('Custom fields: Will broadcast custom fields.'); if (isset($GLOBALS['wpseo_metabox'])) { $this->debug('Yoast SEO detected. Activating workaround. Asking metabox to save its settings.'); $GLOBALS['wpseo_metabox']->save_postdata($bcd->post->ID); } // Save the original custom fields for future use. $bcd->custom_fields->original = get_post_custom($bcd->post->ID); // Obsolete! $bcd->post_custom_fields = $bcd->custom_fields->original; $this->debug('The custom fields are <pre>%s</pre>', $bcd->custom_fields()->to_array()); // Start handling the thumbnail unset($bcd->thumbnail); $bcd->has_thumbnail = $bcd->custom_fields()->has('_thumbnail_id'); // Check that the thumbnail ID is > 0 if ($bcd->has_thumbnail) { $thumbnail_id = $bcd->custom_fields()->get_single('_thumbnail_id'); $thumbnail_post = get_post($thumbnail_id); $bcd->has_thumbnail = $thumbnail_id > 0 && $thumbnail_post !== null; } if ($bcd->has_thumbnail) { $bcd->thumbnail_id = $thumbnail_id; $this->debug('Custom fields: Post has a thumbnail (featured image): %s', $bcd->thumbnail_id); $bcd->thumbnail = $thumbnail_post; $bcd->custom_fields()->forget('_thumbnail_id'); // There is a new thumbnail id for each blog. try { $data = attachment_data::from_attachment_id($thumbnail_id); $data->set_attached_to_parent($bcd->post); $bcd->attachment_data[$thumbnail_id] = $data; } catch (Exception $e) { $this->debug('Exception adding attachment: ' . $e->getMessage()); } } else { $this->debug('Custom fields: Post does not have a thumbnail (featured image).'); } $bcd->custom_fields->blacklist = array_filter(explode(' ', $this->get_site_option('custom_field_blacklist'))); $this->debug('The custom field blacklist is: %s', $bcd->custom_fields->blacklist); $bcd->custom_fields->protectlist = array_filter(explode(' ', $this->get_site_option('custom_field_protectlist'))); $this->debug('The custom field protectlist is: %s', $bcd->custom_fields->protectlist); $bcd->custom_fields->whitelist = array_filter(explode(' ', $this->get_site_option('custom_field_whitelist'))); $this->debug('The custom field whitelist is: %s', $bcd->custom_fields->whitelist); foreach ($bcd->custom_fields() as $custom_field => $ignore) { $keep = true; // Skip the exceptions. if ($bcd->custom_fields()->blacklist_has($custom_field)) { $keep = false; } // If we do not broadcast them, then check the whitelist. if (!$keep and $bcd->custom_fields()->whitelist_has($custom_field)) { $keep = true; } if (!$keep) { $this->debug('Custom fields: Deleting custom field %s', $custom_field); $bcd->custom_fields()->forget($custom_field); } else { $this->debug('Custom fields: Keeping custom field %s', $custom_field); } } } else { $this->debug('Will not broadcast custom fields.'); } // Handle any galleries. $bcd->galleries = new collection(); $matches = $this->find_shortcodes($bcd->post->post_content, 'gallery'); $this->debug('Found %s gallery shortcodes.', count($matches[2])); // [2] contains only the shortcode command / key. No options. foreach ($matches[2] as $index => $key) { // We've found a gallery! $bcd->has_galleries = true; $gallery = (object) []; $bcd->galleries->push($gallery); // Complete matches are in 0. $gallery->old_shortcode = $matches[0][$index]; // Extract the IDs $gallery->ids_string = preg_replace('/.*ids=\\"([0-9,]*)".*/', '\\1', $gallery->old_shortcode); $this->debug('Gallery %s has IDs: %s', $gallery->old_shortcode, $gallery->ids_string); $gallery->ids_array = explode(',', $gallery->ids_string); foreach ($gallery->ids_array as $id) { $this->debug('Gallery has attachment %s.', $id); try { $data = attachment_data::from_attachment_id($id); $data->set_attached_to_parent($bcd->post); $bcd->attachment_data[$id] = $data; } catch (Exception $e) { $this->debug('Exception adding attachment: ' . $e->getMessage()); } } } // Handle sticky status. This can be done in two ways: by _POST and by the options. // If the user is using the nromal editor, look in the post. if (isset($_POST['_wp_http_referer'])) { $this->debug('Sticky data found in POST.'); $bcd->post_is_sticky = isset($_POST['sticky']); } else { // Look in the options table. $this->debug('Looking for sticky data via a function.'); $bcd->post_is_sticky = is_sticky($bcd->post->ID); } $this->debug('Post sticky status: %s', intval($bcd->post_is_sticky)); // POST is no longer needed. Empty it so that other plugins don't use it. $action = new actions\maybe_clear_post(); $action->post = $_POST; $action->execute(); // This is for any other plugins that might be interested in the _POST. $_POST = $action->post; // This is a stupid exception: edit_post() checks the _POST for the sticky checkbox. // And edit_post() is run after save_post()... :( // So if the post is sticky, we have to put the checkbox back in the post. // This can be avoided by either not clearing the post or forcing the user to update twice. // Neither solution is any good: not clearing the post makes _some_ plugins go crazy, updating twice is not expected behavior. if ($bcd->post_is_sticky) { $_POST['sticky'] = 'sticky'; } // wp_upload_dir is incorrect on child sites, so we override it during broadcasting. // See the broadcasting_upload_dir method. $this->__siteurl = get_option('siteurl'); $this->add_action('upload_dir', 'broadcasting_upload_dir'); $action = new actions\broadcasting_started(); $action->broadcasting_data = $bcd; $action->execute(); $this->debug('The attachment data is: %s', $bcd->attachment_data); $this->debug('Beginning child broadcast loop.'); foreach ($bcd->blogs as $child_blog) { $child_blog->switch_to(); $bcd->current_child_blog_id = $child_blog->get_id(); $this->debug('Switched to blog %s (%s)', get_bloginfo('name'), $bcd->current_child_blog_id); // Create new post data from the original stuff. $bcd->new_post = clone $bcd->post; $bcd->new_child_created = false; foreach (['guid', 'ID'] as $key) { unset($bcd->new_post->{$key}); } foreach (['comment_count', 'post_parent'] as $key) { $bcd->new_post->{$key} = 0; } $action = new actions\broadcasting_after_switch_to_blog(); $action->broadcasting_data = $bcd; $action->execute(); if (!$action->broadcast_here) { $this->debug('Skipping this blog.'); $child_blog->switch_from(); continue; } // Force a reload the broadcast data? $bcd->broadcast_data = $this->get_post_broadcast_data($bcd->parent_blog_id, $bcd->post->ID); // Post parent if ($bcd->link && isset($parent_broadcast_data)) { if ($parent_broadcast_data->has_linked_child_on_this_blog()) { $linked_parent = $parent_broadcast_data->get_linked_child_on_this_blog(); $bcd->new_post->post_parent = $linked_parent; } } // Insert new? Or update? Depends on whether the parent post was linked before or is newly linked? $need_to_insert_post = true; if ($bcd->broadcast_data !== null) { if ($bcd->broadcast_data->has_linked_child_on_this_blog()) { $child_post_id = $bcd->broadcast_data->get_linked_child_on_this_blog(); $this->debug('There is already a child post on this blog: %s', $child_post_id); // Does this child post still exist? $child_post = get_post($child_post_id); if ($child_post !== null) { $temp_post_data = $bcd->new_post; $temp_post_data->ID = $child_post_id; wp_update_post($temp_post_data); $bcd->new_post->ID = $child_post_id; $need_to_insert_post = false; } else { $this->debug('Warning: The child post has disappeared. Recreating.'); $need_to_insert_post = true; } } } if ($need_to_insert_post) { $temp_post_data = clone $bcd->new_post; $this->debug('Creating a new post: %s', $temp_post_data); unset($temp_post_data->ID); $result = wp_insert_post($temp_post_data, true); // Did we manage to insert the post properly? if (intval($result) < 1) { $this->debug('Unable to insert the child post.'); continue; } // Yes we did. $bcd->new_post->ID = $result; $bcd->new_child_created = true; $this->debug('New child created: %s', $result); if ($bcd->link) { $this->debug('Adding link to child.'); $bcd->broadcast_data->add_linked_child($bcd->current_child_blog_id, $bcd->new_post('ID')); } } $bcd->equivalent_posts()->set($bcd->parent_blog_id, $bcd->post->ID, $bcd->current_child_blog_id, $bcd->new_post('ID')); $this->debug('Equivalent of %s/%s is %s/%s', $bcd->parent_blog_id, $bcd->post->ID, $bcd->current_child_blog_id, $bcd->new_post('ID')); if ($bcd->taxonomies) { $this->debug('Taxonomies: Starting.'); foreach ($bcd->parent_post_taxonomies as $parent_post_taxonomy => $parent_post_terms) { $this->debug('Taxonomies: %s', $parent_post_taxonomy); // If we're updating a linked post, remove all the taxonomies and start from the top. if ($bcd->link) { if ($bcd->broadcast_data->has_linked_child_on_this_blog()) { wp_set_object_terms($bcd->new_post('ID'), [], $parent_post_taxonomy); } } // Skip this iteration if there are no terms if (!is_array($parent_post_terms)) { $this->debug('Taxonomies: Skipping %s because the parent post does not have any terms set for this taxonomy.', $parent_post_taxonomy); continue; } // Get a list of terms that the target blog has. $target_blog_terms = $this->get_current_blog_taxonomy_terms($parent_post_taxonomy); // Go through the original post's terms and compare each slug with the slug of the target terms. $taxonomies_to_add_to = []; foreach ($parent_post_terms as $parent_post_term) { $found = false; $parent_slug = $parent_post_term->slug; foreach ($target_blog_terms as $target_blog_term) { if ($target_blog_term->slug == $parent_slug) { $this->debug('Taxonomies: Found existing taxonomy %s.', $parent_slug); $found = true; $taxonomies_to_add_to[] = intval($target_blog_term->term_id); break; } } // Should we create the taxonomy term if it doesn't exist? if (!$found) { // Does the term have a parent? $target_parent_id = 0; if ($parent_post_term->parent != 0) { // Recursively insert ancestors if needed, and get the target term's parent's ID $target_parent_id = $this->insert_term_ancestors($parent_post_term, $parent_post_taxonomy, $target_blog_terms, $bcd->parent_blog_taxonomies[$parent_post_taxonomy]['terms']); } $new_term = clone $parent_post_term; $new_term->parent = $target_parent_id; $action = new actions\wp_insert_term(); $action->taxonomy = $parent_post_taxonomy; $action->term = $new_term; $action->execute(); if ($action->new_term) { $term_id = intval($action->new_term->term_id); $taxonomies_to_add_to[] = $term_id; $this->debug('Taxonomies: Created taxonomy %s (%s).', $parent_post_term->name, $term_id); } else { $this->debug('Taxonomies: Taxonomy %s was not created.', $parent_post_term->name); } } } $this->debug('Taxonomies: Syncing terms.'); $this->sync_terms($bcd, $parent_post_taxonomy); $this->debug('Taxonomies: Synced terms.'); if (count($taxonomies_to_add_to) > 0) { // This relates to the bug mentioned in the method $this->set_term_parent() delete_option($parent_post_taxonomy . '_children'); clean_term_cache('', $parent_post_taxonomy); $this->debug('Setting taxonomies for %s: %s', $parent_post_taxonomy, $taxonomies_to_add_to); wp_set_object_terms($bcd->new_post('ID'), $taxonomies_to_add_to, $parent_post_taxonomy); } } $this->debug('Taxonomies: Finished.'); } // Maybe remove the current attachments. if ($bcd->delete_attachments) { $attachments_to_remove = get_children('post_parent=' . $bcd->new_post('ID') . '&post_type=attachment'); $this->debug('%s attachments to remove.', count($attachments_to_remove)); foreach ($attachments_to_remove as $attachment_to_remove) { $this->debug('Deleting existing attachment: %s', $attachment_to_remove->ID); wp_delete_attachment($attachment_to_remove->ID); } } else { $this->debug('Not deleting child attachments.'); } // Copy the attachments $bcd->copied_attachments = []; $this->debug('Looking through %s attachments.', count($bcd->attachment_data)); foreach ($bcd->attachment_data as $key => $attachment) { $o = clone $bcd; $o->attachment_data = clone $attachment; $o->attachment_data->post = clone $attachment->post; $this->debug("The attachment's post parent is %s.", $o->attachment_data->post->post_parent); if ($o->attachment_data->is_attached_to_parent()) { $this->debug('Assigning new post parent ID (%s) to attachment %s.', $bcd->new_post('ID'), $o->attachment_data->post->ID); $o->attachment_data->post->post_parent = $bcd->new_post('ID'); } else { $this->debug('Resetting post parent for attachment %s.', $o->attachment_data->post->ID); $o->attachment_data->post->post_parent = 0; } $this->maybe_copy_attachment($o); $bcd->copied_attachments()->add($attachment->post, get_post($o->attachment_id)); $this->debug('Copied attachment %s to %s', $attachment->post->ID, $o->attachment_id); } // Maybe modify the post content with new URLs to attachments and what not. $unmodified_post = (object) $bcd->new_post; $modified_post = clone $unmodified_post; // If there were any image attachments copied... if (count($bcd->copied_attachments()) > 0) { $this->debug('%s attachments were copied.', count($bcd->copied_attachments())); // Update the URLs in the post to point to the new images. $new_upload_dir = wp_upload_dir(); foreach ($bcd->copied_attachments() as $a) { $count = 0; // Replace the GUID with the new one. $modified_post->post_content = str_replace($a->old->guid, $a->new->guid, $modified_post->post_content, $count); if ($count > 0) { $this->debug('Modified attachment guid from %s to %s: %s times', $a->old->guid, $a->new->guid, $count); } // And replace the IDs present in any image captions. $modified_post->post_content = str_replace('id="attachment_' . $a->old->id . '"', 'id="attachment_' . $a->new->id . '"', $modified_post->post_content, $count); if ($count > 0) { $this->debug('Modified attachment link from %s to %s: %s times', $a->old->id, $a->new->id, $count); } } } else { $this->debug('No attachments were copied.'); } // If there are galleries... $this->debug('%s galleries are to be handled.', count($bcd->galleries)); foreach ($bcd->galleries as $gallery) { // Work on a copy. $gallery = clone $gallery; $new_ids = []; // Go through all the attachment IDs foreach ($gallery->ids_array as $id) { $new_id = $bcd->copied_attachments()->get($id); if ($new_id) { $new_ids[] = $new_id; } } $new_ids_string = implode(',', $new_ids); $new_shortcode = $gallery->old_shortcode; $new_shortcode = str_replace($gallery->ids_string, $new_ids_string, $gallery->old_shortcode); $this->debug('Replacing gallery shortcode %s with %s.', $gallery->old_shortcode, $new_shortcode); $modified_post->post_content = str_replace($gallery->old_shortcode, $new_shortcode, $modified_post->post_content); } $bcd->modified_post = $modified_post; $action = new actions\broadcasting_modify_post(); $action->broadcasting_data = $bcd; $action->execute(); $this->debug('Checking for post modifications.'); $post_modified = false; foreach ((array) $unmodified_post as $key => $value) { if ($unmodified_post->{$key} != $modified_post->{$key}) { $this->debug('Post has been modified because of %s.', $key); $post_modified = true; } } // Maybe updating the post is not necessary. if ($post_modified) { $this->debug('Modifying new post.'); wp_update_post($modified_post); // Or maybe it is. } else { $this->debug('No need to modify the post.'); } if ($bcd->custom_fields) { $this->debug('Custom fields: Started.'); $child_fields = $bcd->custom_fields()->child_fields(); $child_fields->load(); // new_post_old_custom_fields is obsolete. Remove the first part in a few versions. $bcd->new_post_old_custom_fields = $child_fields; $this->debug('Custom fields of the child post: %s', $child_fields->to_array()); $protected_field = []; foreach ($child_fields as $key => $value) { // Do we delete this custom field? $delete = true; // For the protectlist to work the custom field has to already exist on the child. if ($bcd->custom_fields()->protectlist_has($key)) { if (!$child_fields->has($key)) { continue; } if (!$bcd->custom_fields()->has($key)) { continue; } $protected_field[$key] = true; $delete = false; } if ($delete) { $this->debug('Custom fields: Deleting custom field %s.', $key); $child_fields->delete_meta($key); } else { $this->debug('Custom fields: Keeping custom field %s.', $key); } } foreach ($bcd->custom_fields() as $meta_key => $meta_value) { // Protected = ignore. if (isset($protected_field[$meta_key])) { continue; } if (is_array($meta_value)) { foreach ($meta_value as $single_meta_value) { $single_meta_value = maybe_unserialize($single_meta_value); $this->debug('Custom fields: Adding array value %s', $meta_key); $child_fields->add_meta($meta_key, $single_meta_value); } } else { $meta_value = maybe_unserialize($meta_value); $this->debug('Custom fields: Adding value %s', $meta_key); $child_fields->add_meta($meta_key, $meta_value); } } // Attached files are custom fields... but special custom fields. if ($bcd->has_thumbnail) { $new_thumbnail_id = $bcd->copied_attachments()->get($bcd->thumbnail_id); $this->debug('Handling post thumbnail for post %s. Thumbnail ID is now %s', $bcd->new_post('ID'), $new_thumbnail_id); update_post_meta($bcd->new_post('ID'), '_thumbnail_id', $new_thumbnail_id); } $this->debug('Custom fields: Finished.'); } // Sticky behaviour $child_post_is_sticky = is_sticky($bcd->new_post('ID')); $this->debug('Sticky status: %s', intval($child_post_is_sticky)); if ($bcd->post_is_sticky && !$child_post_is_sticky) { $this->debug('Sticking post.'); stick_post($bcd->new_post('ID')); } if (!$bcd->post_is_sticky && $child_post_is_sticky) { $this->debug('Unsticking post.'); unstick_post($bcd->new_post('ID')); } if ($bcd->link) { $new_post_broadcast_data = $this->get_post_broadcast_data($bcd->current_child_blog_id, $bcd->new_post('ID')); $new_post_broadcast_data->set_linked_parent($bcd->parent_blog_id, $bcd->post->ID); $this->debug('Saving broadcast data of child: %s', $new_post_broadcast_data); $this->set_post_broadcast_data($bcd->current_child_blog_id, $bcd->new_post('ID'), $new_post_broadcast_data); // Save the parent also. $this->debug('Saving parent broadcast data: %s', $bcd->broadcast_data); $this->set_post_broadcast_data($bcd->parent_blog_id, $bcd->post->ID, $bcd->broadcast_data); } $action = new actions\broadcasting_before_restore_current_blog(); $action->broadcasting_data = $bcd; $action->execute(); $child_blog->switch_from(); } // SEE: For nested broadcasts. Just in case. restore_current_blog(); $action = new actions\broadcasting_finished(); $action->broadcasting_data = $bcd; $action->execute(); // We are done with the upload dir override. unset($this->__siteurl); remove_action('upload_dir', [$this, 'broadcasting_upload_dir']); // Finished broadcasting. array_pop($this->broadcasting); if ($this->debugging_to_browser()) { if (!$this->is_broadcasting()) { if (isset($bcd->stop_after_broadcast) && !$bcd->stop_after_broadcast) { $this->debug('Finished broadcasting.'); } else { $this->debug('Finished broadcasting. Now stopping Wordpress.'); exit; } } else { $this->debug('Still broadcasting.'); } } $this->load_language(); return $bcd; }