Cms: [Feature Request] Moving entries (with descendants) between Sites

Created on 31 Mar 2019  路  13Comments  路  Source: craftcms/cms

Would it be possible to add the ability to move entries with descendants to other sites?
The specific use case for me is a site where I did a hacky multisite setup with all entries/sites in the same locale ("sites" were represented by the top level entry of a structure and we cut that entries slug out of the URL). I need to move each of those "sites" (top level entries) to a separate Site after the Craft 3 update.
I'm sure this would come in handy in a lot of different scenarios aswell.

content modeling enhancement

Most helpful comment

So basically for a section where entries are not propagated to other sites, you just want a way to move entries to different sites.

All 13 comments

Not sure I鈥檓 following you. When you upgrade to Craft 3, you can have your section be enabled for multiple sites, at which point its entries will be available across all of those sites as well.

I currently have all of my entries in one Site and I would like to create a bunch of sites (they would be running on separate domains with different content but with the same templates, sections, and assets) and move each of those entries to a separate site.

So in a setup where a sections entries propagation is disabled - taking this:

Main Site
 - Top Entry 1
 - - Child
 - - Child 
 - Top Entry 2
 - - Child 
 - Top Entry 3
 - - Child
 - - - Grandchild
 - - Child 

And turning it into something like this:

Main Site
 - Top Entry 1
 - - Child
 - - Child 

Second Site
 - Top Entry 2
 - - Child 

Third Site
 - Top Entry 3
 - - Child
 - - - Grandchild
 - - Child 

I hope it makes more sense now! :D
If you are at any time available for a chat on Discord, I would be happy to try and elaborate on this, including project specific details which I can not disclose here, publicly. That could help in understanding what we are trying to achieve.

So basically for a section where entries are not propagated to other sites, you just want a way to move entries to different sites.

Exactly! I assume it's not something that will be added soon, which means that for this project we will probably copy paste the content entry by entry (as annoying as that might be), but it would be an amazing feature to have in the future.

Edit: The following steps don't currently work as I had hoped. Entries get removed from the new site when propagation is disabled.

@pgrzyb In the meantime, if you haven't set up your new sites yet, you _might_ be able to simply:

  • Enable Propagate entries across all enabled sites? for your structure.
  • Add your new sites to that structure. (triggers re-saves which duplicates entries to those sites)
  • Disable Propagate entries across all enabled sites?
  • Delete entries that shouldn't exist for each site.

This doesn't solve the issue for moving entries between sites once they're established, but might help you save some time moving content.

_Edit: Actually, you could probably do this even if you've already added the sites to the structure by just removing the sites and following the steps listed._

Hey @jsunsawyer, thanks for pitching in! I have actually previously tried that (back in craft 3.0.*) and disabling Propagate entries across all enabled sites? removed all entries from the "extra" sites. Not sure if the functionality was changed since then. I will give that another go :)

@pgrzyb Oooh, didn't think it'd work like that. Let me know what happens!

@pgrzyb Just did a quick test and you're right, unfortunately. I also tried to duplicate entries from the new site in that section in hopes that Craft would treat them as belonging to the new site, but no such luck.

Yep, that is unfortunate. I hoped that I could use a plugin called Site Duplicate, but that only supports copying a single entry, without its descendants. It's "a solution" but it doesn't fall far from just copying the content manually, especially that we can fix things up a bit in the process :P

You should be able to move the entry by running these SQL queries:

UPDATE `elements_sites` SET `siteId` = <NewSiteID> WHERE `elementId` = <EntryID>;
UPDATE `content` SET `siteId` = <NewSiteID> WHERE `elementId` = <EntryID>;
UPDATE `searchindex` SET `siteId` = <NewSiteID> WHERE `elementId` = <EntryID>;

(Only run that if you鈥檙e sure the section is set to not propagate entries across multiple sites, and probably re-save the entry from the Control Panel first.)

If you have a DB table prefix like craft_, you鈥檒l need to update those table names first.

And if you鈥檙e using PostgreSQL, replace the `s with "s.

@brandonkelly That will not affect descendants, right? Any suggestions on how i could apply this to an Entry + all of its descendants in a fairly simple way? I could get each entries ID's manually and just go 1 by 1, but with this amount of content, seppuku sounds like a more exciting alternative :)

You could do it with a PHP script. Start by copying your current web/index.php file as web/move-entries.php, and in the copy, delete the $app->run(); line at the end. Then add this to the file:

// Change these values:
$oldSiteId = 1;
$newSiteId = 2;
$sectionHandle = 'mySection';
$entryId = 10;

// Find all the entry IDs we need to move
$ids = array_merge(
    [10], 
    craft\elements\Entry::find()
        ->section($sectionHandle)
        ->descendantOf($entryId)
        ->anyStatus()
        ->ids();

if (empty($ids)) {
    echo 'Nothing to update';
    exit();
}

$app->db->createCommand()
    ->update('{{%elements_sites}}', ['siteId' => $newSiteId], ['elementId' => $ids], [], false)
    ->execute();
$app->db->createCommand()
    ->update('{{%content}}', ['siteId' => $newSiteId], ['elementId' => $ids], [], false)
    ->execute();
$app->db->createCommand()
    ->update('{{%searchindex}}', ['siteId' => $newSiteId], ['elementId' => $ids], [], false)
    ->execute();

echo 'Updated ' . count($ids) . ' entries';

Replace all the values at the top accordingly, and then access the script from your browser.

You should be able to move the entry by running these SQL queries:

UPDATE `elements_sites` SET `siteId` = <NewSiteID> WHERE `elementId` = <EntryID>;
UPDATE `content` SET `siteId` = <NewSiteID> WHERE `elementId` = <EntryID>;
UPDATE `searchindex` SET `siteId` = <NewSiteID> WHERE `elementId` = <EntryID>;

(Only run that if you鈥檙e sure the section is set to not propagate entries across multiple sites, and probably re-save the entry from the Control Panel first.)

If you have a DB table prefix like craft_, you鈥檒l need to update those table names first.

And if you鈥檙e using PostgreSQL, replace the `s with "s.

@brandonkelly I have a similar issue, regarding a single section and translatable fields. Essentially I made the fields translatable and the content was saved to the wrong site. Would you be able to suggest which DB updates would need to be made to rectify this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

leigeber picture leigeber  路  3Comments

mattstein picture mattstein  路  3Comments

brandonkelly picture brandonkelly  路  3Comments

mccombs picture mccombs  路  3Comments

darylknight picture darylknight  路  3Comments