One doesn't simply get a list of permissionable SObjects.
Looks like there is no simple way to find that.
However, the error wording suggest that SobjectType
field on ObjectPermissions
object is a picklist which is even restricted, so it should be possible to retrieve its picklist options.
Let's define some helper methods to retrieve picklist options first.
/**
* @description Retrieves Picklist Entries for specified field
* @param obj object type
* @param field picklist field
* @return Picklist Entries
*/
public static Schema.PicklistEntry[] getPicklistValues( Schema.SObjectType obj, SObjectField field ) {
return obj.getDescribe().fields.getMap().get(String.valueOf(field)).getDescribe().getPicklistValues();
}
/**
* @description Retrieves list of picklist values
* @param obj SObject type
* @param field SObject field
* @return List of picklist values
*/
public static List<String> getPicklistValuesList( Schema.SObjectType obj, SObjectField field ) {
List<String> results = new List<String>();
for (PicklistEntry entry: getPicklistValues(obj, field) ) {
results.add(entry.getValue());
}
return results;
}
Next, let's try to get a list of Picklist Options for SobjectType field on ObjectPermissions. It is also tricky because to get ObjectPermission sobject token we need to use workaround since its field token blocks access to object token because Apex is case insensitive
System.debug(LoggingLevel.ERROR, '@@@ v: ' + getPicklistValues(
Schema.sObjectType.ObjectPermissions.getSobjectType(),
ObjectPermissions.SobjectType
) );
Here we go.
However, this picklist has empty labels. So, to retrieve the labels, we still need to call Schema.describeSObjects
passing objects found by the previous method.
There is another obstacle here, picklist options may include many objects which do not even exist on our instance and we will get exception for such objects.
For my developer edition instance, such unavailable objects are
AccountBrand, AccountRelationship, ActionCadence, ActionCadenceStep, ActionCadenceStepTracker, ActionCadenceTracker, ActionPlan, ActionPlanTemplate, ActiveScratchOrg, AddOnDefinition, Address, AggregationRow, AiImageDetectedObject, AiImageObject, AiImageTrainingObject, AppIntelQueryRequest, CardPaymentMethod, CareBarrier, CareBarrierDeterminant, CareBarrierType, CareDeterminant, CareDeterminantType, CareDiagnosis, CareInterventionType, CarePreauth, CarePreauthItem, CareProgram, CareProgramCampaign, CareProgramEnrollee, CareProgramTeamMember, CareRequest, CareRequestDrug, CareRequestItem, Certification, CertificationDef, CertificationSectionDef, CertificationStep, CertificationStepDef, ChannelProgram, ChannelProgramLevel, ChannelProgramMember, Claim, CloudServiceProvider, CloudServiceProviderApi, ConsumptionSchedule, ContactPointAddress, ContactPointConsent, ContactPointEmail, ContactPointPhone, ContactPointTypeConsent, ContractLineItem, CoverageBenefit, CoverageBenefitItem, CoverageType, CustomerAssetAuto, CustomerAssetHome, DataSharingCustomerLocal, DataUseLegalBasis, DataUsePurpose, EditionDefinition, EngagementProgram, EngagementProgramNode, EngagementProgramVersion, Entitlement, EntitlementContact, EnvironmentHubInvitation, EnvironmentHubMember, FtestAccountChild, FtestChild, FtestConcrete, FtestConcrete2, FtestConcrete3, FtestConcrete4, FtestConcrete5, FtestConcrete6, FtestConcrete7, FtestConcrete8, FtestConcreteNoDefault, FtestConcreteNoDefault2, FtestConcreteNoDefault3, FtestConcreteNoSup, FtestConcreteNoSup2, FtestConcreteNoSup3, FtestError, FtestErrorChild, FtestGrandChild, FtestHiddenName, FtestMain, FtestOffCoreRecord, FtestPerson, FtestVirtualMain, Goal, GoalLink, HealthCareDiagnosis, HealthCareProcedure, IdeaTheme, IdentityDocument, IncludedLicenseDefinition, Individual, InStoreLocation, InsurancePolicy, InsurancePolicyAsset, InsurancePolicyBeneficiary, InsurancePolicyCoverageLimit, InsurancePolicyMember, InsuranceProfile, KeyPerformanceIndicator, LicensingError, LicensingRequest, LiveAgentSession, LiveChatTranscript, LiveChatVisitor, Location, MaintenancePlan, ManagementAddOnLicense, ManagementEditionLicense, ManagementPlatformLicense, ManagementUserLicense, MemberPlan, MessagingEndUser, MessagingSession, Metric, MetricDataLink, MyCustomObject, NamespaceRegistry, OperatingHours, OrderDeliveryGroup, OrderDeliveryGroupLine, OrderDeliveryMethod, OrderItemSummary, OrderPriceAdjustDistrLine, OrderSummary, OrgSnapshot, PartnerFundAllocation, PartnerFundClaim, PartnerFundRequest, PartnerMarketingBudget, PaymentAuthorization, PaymentGroup, PersonEducation, PersonEmployment, PersonLifeEvent, PersonList, PlanBenefit, PlanBenefitItem, PlatformLicenseDefinition, Producer, ProductCoverage, ProductItem, ProductRequest, ProductTransfer, ProfileSkill, ProfileSkillEndorsement, ProfileSkillUser, PurchaserPlan, PurchaserPlanAssn, Question, Quote, RegisteredMobileDevice, RetailLocationGroup, RetailStore, RetailStoreKpi, RetailStoreVisitTemplate, RetailVisitKpi, RetailVisitTemplate, RetailVisitTemplateWorkTask, RetailVisitWorkTask, RetailWorkTask, RetailWorkTaskKpi, ReturnOrder, SalesAgreement, Scorecard, ScorecardAssociation, ScorecardMetric, ScratchOrgInfo, ServiceAppointment, ServiceContract, ServiceCrew, ServiceResource, ServiceTerritory, SettingUsageDefinition, SettingUsageMap, ShapeRepresentation, Shipment, SignupRequest, SocialPost, Survey, SurveyInvitation, SurveyResponse, SurveySubject, Tenant, TenantParameterMap, TimeSheet, TrialEnvironmentSignup, UsageEntitlement, UsageFactor, UserLicenseDefinition, Visit, WebStore, WorkCapacityLimit, WorkCoaching, WorkFeedback, WorkFeedbackQuestion, WorkFeedbackQuestionSet, WorkFeedbackRequest, WorkFeedbackTemplate, WorkGoal, WorkGoalCollaborator, WorkGoalLink, WorkOrder, WorkPerformanceCycle, WorkReward, WorkRewardFund, WorkRewardFundType, WorkType, WorkTypeGroup, WorkUpgradeAction, WorkUpgradeCustomer, WorkUpgradeUser.
So we need a way to filter them out.
The only option I currently have found it to catch an exception there and hope we don't exceed Describe call limit for an organization.
List<Map<String, String>> results = new List<Map<String, String>>();
for ( String o: getPicklistValuesList(
Schema.sObjectType.ObjectPermissions.getSobjectType(),
ObjectPermissions.SobjectType
) ) {
try{
for (DescribeSObjectResult describeResult: Schema.describeSObjects(
new List<String>{o}
) ) {
results.add(new Map<String, String>{'label'=>describeResult.getLabel(), 'value'=>describeResult.getName()});
}
} catch (Exception e) {
//failed.add(o);
}
}
/*for (DescribeSObjectResult describeResult: Schema.describeSObjects(
getPicklistValuesList(
Schema.sObjectType.ObjectPermissions.getSobjectType(),
ObjectPermissions.SobjectType
)
) ) {
results.add(new Map<String, String>{'label'=>describeResult.getLabel(), 'value'=>describeResult.getName()});
}*/
return results;
Phil W suggested to use Global Describe instead of catching an error, so I refactored my method into following form:
List<Map<String, String>> results = new List<Map<String, String>>();
Map<String, SObjectType> globalDescribe = Schema.getGlobalDescribe();
for ( String o: getPicklistValuesList(
Schema.sObjectType.ObjectPermissions.getSobjectType(),
ObjectPermissions.SobjectType
) ) {
if ( globalDescribe.containsKey(o)) {
DescribeSObjectResult result = globalDescribe.get(o).getDescribe();
results.add(new Map<String, String>{'label'=>result.getLabel(), 'value'=>result.getName()});
}
}
return results;