-
-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Set-ItemTemplate not copying all languages and all versions, if field ID is different #1259
Comments
WIP : You can now do this and it will Skip any fields that are detected as StandardValue. $item = Get-Item -Path "master:{0633B0E2-BFF7-4E91-8558-41C9ABE8C46E}"
$newTemplateId = "{5A2C318B-2CD7-4601-A264-FB74CAC6F3F8}"
$fields = @{ "Field1" = "Field1"; "Field2" = "Field2" }
$item | Set-ItemTemplate -Template $newTemplateId -FieldsToCopy $fields -FieldCopyBehavior SkipStandardValue |
Inspecting the Sitecore library, The only difference I see in the Sitecore code is there is some special handling for cloned items. |
From what I can tell after decompiling, Seems like that method performs an additional loop through the item's field list to check for field name if field ID doesn't exist in the new template:
Thanks for the new FieldCopyBehavior flag, but can you make it possible for -FieldsToCopy to copy field values for all languages and versions? It's kind of a let-down if I'm only able to copy over the values for the active item version (v3 en) only, and not the others like v2 en or v1 en or v3 de. If it helps, my current workaround was to do a loop through in $item.Versions.GetVersions($true) to store the relevant field values for each version/language before changing the template. |
I'll check to see how the languages/versions are handled. I did notice that the "Change Template" UI is doing something different. Current SPE: TemplateManager.ChangeTemplate(item, new TemplateChangeList(oldTemplate, newTemplate)); Sitecore UI: var changeList = oldTemplate.GetTemplateChangeList(newTemplate);
TemplateManager.ChangeTemplate(item, changeList); |
This is consistent with the Change Template UI in the Content Editor.
This will cause the fields to be copied like the Change Template UI. $item = Get-Item -Path "master:{0633B0E2-BFF7-4E91-8558-41C9ABE8C46E}"
$newTemplateId = "{5A2C318B-2CD7-4601-A264-FB74CAC6F3F8}"
$item | Set-ItemTemplate -Template $newTemplateId Don't copy any fields $item = Get-Item -Path "master:{0633B0E2-BFF7-4E91-8558-41C9ABE8C46E}"
$newTemplateId = "{5A2C318B-2CD7-4601-A264-FB74CAC6F3F8}"
$item | Set-ItemTemplate -Template $newTemplateId -FieldsToCopy @{ } |
Thinking about it further, you should be able to explicitly get the versions and languages you desire: Get-Item -Path "master:\content\home" -Version * -Language * |
Hm, you're not updating the parameter for TemplateManager.ChangeTemplate in your latest change for SetItemTemplateCommand.cs in line 108?
True, I sometimes use c# code in my scripts since I remember them easier lol. Just that, after changing the item template, all the other values in the other language versions may be no longer accessible if you don't remember to store them. |
The way I look at it, if you are going to specify the fields to copy then you don't need the change list to include more fields. Right? |
Haha true, then you should include in the documentation that fields copied over when the -FieldsToCopy flag is used will only be by ID, since Sitecore UI does it by ID and name. I wonder though, this code |
It seems to use the ID when getting the field from the source template, and then Name on the target template. You could essentially do this manually with the Hashtable.
As long as we are allowing the developer to provide a list of fields we'll have to loop through. The change list would include more information than that provided by in the Hashtable. I don't see in the code where Sitecore is grabbing all languages. One place it does set the "Preferred Language" as the Context Language. |
Added a way to halt the progress if the field doesn't exist: $item = Get-Item -Path "master:{0633B0E2-BFF7-4E91-8558-41C9ABE8C46E}"
$newTemplateId = "{5A2C318B-2CD7-4601-A264-FB74CAC6F3F8}"
$item | Set-ItemTemplate -Template $newTemplateId -FieldsToCopy @{ "Field1" = "Fieldx" } -FieldCopyBehavior StopOnFieldError |
Yeah, it's quite convulted, I think it's the method Ok, so I tried out the Here's my workaround script that worked out pretty well for my own use:
|
Would you say that the current implementation causes data loss unexpectedly? |
@mikaelnet do you have any insights you can share about this issue? Any recommendations? |
How about add another option to copy the fields? Then the Hashtable can serve as a way to map fields that would not convert properly (not match by name). $item = Get-Item -Path "master:{0633B0E2-BFF7-4E91-8558-41C9ABE8C46E}"
$newTemplateId = "{5A2C318B-2CD7-4601-A264-FB74CAC6F3F8}"
$fieldMapping = @{ "Field2" = "Field3" }
$item | Set-ItemTemplate -Template $newTemplateId -FieldCopyBehavior CopyAllFields -FieldsToCopy $fieldMapping |
IMO, using Additionally, since
Technically |
This is consistent with the Change Template UI in the Content Editor.
Sorry I'm late to this discussion. Not sure if this is still relevant, but I'll share a few thoughts that comes to my mind. Historically, I've been struggling with this as well and I usually end up building my own solution-custom methods for this. I've found it important to validate if a template change is possible in the first place. For example, if an item is a clone or is cloned, the result may be quite unexpected. In a clone scenario one would obviously have some kind of broken/undefined state while changing the source item and all its clones. In a SPE scenario, it could be worth testing if the item is cloned or is a clone and use a When it comes to migrating fields, I think it's essential that content is migrated on all languages/versions, since a template change applies to all. At the same time, it's important to only migrate fields containing actual values. Any fields with Another thing to consider is the |
Expected Behavior
Set-ItemTemplate should perform the same as the c# method
item.ChangeTemplate(templateItem)
.Actual Behavior
When I use Set-ItemTemplate, only field values of the same field ID are preserved.
When I use Set-ItemTemplate with -FieldsToCopy argument, field values are always copied over, even if they are using standard values. Suggest adding a flag to omit copying if the field value is a standard value.
E.g. Template A has field named BannerImage (Item ID: 11111111...) and Template B has field named BannerImage (Item ID: 22222222...)
$item.ChangeTemplate($templateItemB)
copies over such values by default, for all versions and languages.$item | Set-ItemTemplate -TemplateItem $templateItemB
does not copy such values by default.BannerImage value is left blank after changing the template.
$item | Set-ItemTemplate -TemplateItem $templateItemB -FieldsToCopy @{ "BannerImage" = "BannerImage"; }
only copies such values only for the current $item.Version and $item.Language.Other versions and languages do not get the values.
$item | Set-ItemTemplate -TemplateItem $templateItemB -FieldsToCopy @{ "TextOne" = "TextTwo"; }
copies TextOne value explicitly even when it's a standard value, causing the resulting TextTwo field to no longer be using the standard values from Template B.Steps to Reproduce the Problem
$item | Set-ItemTemplate -TemplateItem $templateItem -FieldsToCopy @{ "BannerImage" = "BannerImage"; "TextOne" = "TextTwo" }
Take note BannerImage from source template has a different field ID as compared to BannerImage from target template
The text was updated successfully, but these errors were encountered: