If I understand your question right, all these configurations must end up with the same new Lightning Page (FlexiPage), so let's start.
- Preparations: Create MetadataService class with Setup -> API -> Metadata WSDL. Setup -> Apex Classes -> Generate from WSDL. (Or just get it from git).
- Prepare your
MetadataPort
:
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();
service.CallOptions = new MetadataService.CallOptions_element();
service.timeout_x = 120000;
- Set up your
newLightningPageName
:
String newLightningPageName = 'ORGDEF';
- Read standard home page (Default Home Page in the picture):
MetadataService.CustomTab standardHomeTabForAllApps = ((List <MetadataService.CustomTab>) service.readMetadata('CustomTab', new List<String>{'standard-home'}).getRecords())[0];
- Replace or add action override for custom tab with new lighting page:
Boolean replaced = false;
for (MetadataService.ActionOverride action : standardHomeTabForAllApps.actionOverrides) {
if (action.actionName == 'Tab' && action.type_x == 'FlexiPage') {
action.content = newLightningPageName;
replaced = true;
break;
}
}
if (!replaced) {
MetadataService.ActionOverride newAction = new MetadataService.ActionOverride();
newAction.actionName = 'Tab';
newAction.type_x = 'FlexiPage';
newAction.content = newLightningPageName;
if (standardHomeTabForAllApps.actionOverrides == null) {
standardHomeTabForAllApps.actionOverrides = new List<MetadataService.ActionOverride>();
}
standardHomeTabForAllApps.actionOverrides.add(newAction);
}
service.updateMetadata(new List<MetadataService.CustomTab>{standardHomeTabForAllApps});
- Retrieve all your applications names:
MetadataService.ListMetadataQuery query = new MetadataService.ListMetadataQuery();
query.type_x = 'CustomApplication';
List<MetadataService.FileProperties> applications = service.listMetadata(new List<MetadataService.ListMetadataQuery>{query}, 53);
List<String> applicationsNames = new List<String>();
for (MetadataService.FileProperties application : applications) {
if (String.isNotBlank(application.fullName)) {
applicationsNames.add(application.fullName);
}
}
- Read your applications metadata:
List<MetadataService.CustomApplication> applicationsMetadata = (List <MetadataService.CustomApplication>) service.readMetadata('CustomApplication', applicationsNames).getRecords();
- Replace action override (only replace without adding, because org default home page is already set up):
List<MetadataService.CustomApplication> applicationsMetadataToUpdate = new List<MetadataService.CustomApplication>();
for (MetadataService.CustomApplication applicationMetadata : applicationsMetadata) {
if (applicationMetadata.uiType == 'Lightning') { //works for lightning apps only
if (applicationMetadata.actionOverrides != null) {
for (MetadataService.AppActionOverride action : applicationMetadata.actionOverrides) { //Assignments by App
if (action.pageOrSobjectType == 'standard-home' && action.actionName == 'Tab' && action.type_x == 'FlexiPage') {
action.content = newLightningPageName;
}
}
}
if (applicationMetadata.profileActionOverrides != null) {
for (MetadataService.AppProfileActionOverride action : applicationMetadata.profileActionOverrides) { //Assignments by App and Profile
if (action.pageOrSobjectType == 'standard-home' && action.actionName == 'Tab' && action.type_x == 'FlexiPage') {
action.content = newLightningPageName;
}
}
}
applicationsMetadataToUpdate.add(applicationMetadata);
}
}
Integer MAX_BATCH_METADATA_SIZE = 10;
List<MetadataService.CustomApplication> batch = new List<MetadataService.CustomApplication>();
for (MetadataService.CustomApplication application : applicationsMetadataToUpdate) {
batch.add(application);
if (batch.size() == MetadataHelper.MAX_BATCH_METADATA_SIZE) {
service.updateMetadata(batch);
batch.clear();
}
}
if (batch.size() > 0) {
service.updateMetadata(batch);
}
Important note: if you are going to use MetadataService
from git, you will need to update several classes like this:
public virtual class GlobalActionOverride extends Metadata {
public String fullName;
public String actionName;
public String comment;
public String content;
public String formFactor;
public Boolean skipRecordTypeSelect;
public String type_x;
private String[] fullName_type_info = new String[]{'fullName',SOAP_M_URI,null,'0','1','false'};
private String[] actionName_type_info = new String[]{'actionName',SOAP_M_URI,null,'0','1','false'};
private String[] comment_type_info = new String[]{'comment',SOAP_M_URI,null,'0','1','false'};
private String[] content_type_info = new String[]{'content',SOAP_M_URI,null,'0','1','false'};
private String[] formFactor_type_info = new String[]{'formFactor',SOAP_M_URI,null,'0','1','false'};
private String[] skipRecordTypeSelect_type_info = new String[]{'skipRecordTypeSelect',SOAP_M_URI,null,'0','1','false'};
private String[] type_x_type_info = new String[]{'type',SOAP_M_URI,null,'0','1','false'};
private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
private String[] field_order_type_info = new String[]{'fullName','actionName','comment','content','formFactor','skipRecordTypeSelect','type_x'};
}
public class AppActionOverride extends GlobalActionOverride {
public String type = 'AppActionOverride';
public String fullName;
private String[] fullName_type_info = new String[]{'fullName',SOAP_M_URI,null,'0','1','false'};
public String actionName;
public String comment;
public String content;
public String formFactor;
public Boolean skipRecordTypeSelect;
public String pageOrSobjectType;
public String type_x;
private String[] actionName_type_info = new String[]{'actionName',SOAP_M_URI,null,'0','1','false'};
private String[] comment_type_info = new String[]{'comment',SOAP_M_URI,null,'0','1','false'};
private String[] content_type_info = new String[]{'content',SOAP_M_URI,null,'0','1','false'};
private String[] formFactor_type_info = new String[]{'formFactor',SOAP_M_URI,null,'0','1','false'};
private String[] skipRecordTypeSelect_type_info = new String[]{'skipRecordTypeSelect',SOAP_M_URI,null,'0','1','false'};
private String[] type_x_type_info = new String[]{'type',SOAP_M_URI,null,'0','1','false'};
private String[] pageOrSobjectType_type_info = new String[]{'pageOrSobjectType',SOAP_M_URI,null,'1','1','false'};
private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
private String[] type_att_info = new String[]{'xsi:type'};
private String[] field_order_type_info = new String[]{'fullName','actionName','comment','content','formFactor','skipRecordTypeSelect','type_x','pageOrSobjectType'};
}
public class AppProfileActionOverride extends GlobalActionOverride {
public String type = 'AppProfileActionOverride';
public String fullName;
private String[] fullName_type_info = new String[]{'fullName',SOAP_M_URI,null,'0','1','false'};
public String actionName;
public String comment;
public String content;
public String formFactor;
public Boolean skipRecordTypeSelect;
public String type_x;
public String pageOrSobjectType;
public String profile;
private String[] actionName_type_info = new String[]{'actionName',SOAP_M_URI,null,'0','1','false'};
private String[] comment_type_info = new String[]{'comment',SOAP_M_URI,null,'0','1','false'};
private String[] content_type_info = new String[]{'content',SOAP_M_URI,null,'0','1','false'};
private String[] formFactor_type_info = new String[]{'formFactor',SOAP_M_URI,null,'0','1','false'};
private String[] skipRecordTypeSelect_type_info = new String[]{'skipRecordTypeSelect',SOAP_M_URI,null,'0','1','false'};
private String[] type_x_type_info = new String[]{'type',SOAP_M_URI,null,'0','1','false'};
private String[] pageOrSobjectType_type_info = new String[]{'pageOrSobjectType',SOAP_M_URI,null,'1','1','false'};
private String[] profile_type_info = new String[]{'profile',SOAP_M_URI,null,'1','1','false'};
private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
private String[] type_att_info = new String[]{'xsi:type'};
private String[] field_order_type_info = new String[]{'fullName','actionName','comment','content','formFactor','skipRecordTypeSelect','type_x','pageOrSobjectType','profile'};
}
public class ReadGlobalActionOverrideResult implements IReadResult {
public MetadataService.GlobalActionOverride[] records;
public MetadataService.Metadata[] getRecords() { return records; }
private String[] records_type_info = new String[]{'records',SOAP_M_URI,null,'0','-1','false'};
private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
private String[] field_order_type_info = new String[]{'records'};
}
public class readGlobalActionOverrideResponse_element implements IReadResponseElement {
public MetadataService.ReadGlobalActionOverrideResult result;
public IReadResult getResult() { return result; }
private String[] result_type_info = new String[]{'result',SOAP_M_URI,null,'1','1','false'};
private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
private String[] field_order_type_info = new String[]{'result'};
}