diff --git a/sfdx-source/apex-extensions/main/default/classes/selectors/fflib_SObjectShareSelector.cls b/sfdx-source/apex-extensions/main/default/classes/selectors/fflib_SObjectShareSelector.cls new file mode 100644 index 0000000..38d6d56 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/selectors/fflib_SObjectShareSelector.cls @@ -0,0 +1,121 @@ +/** + * File Name: fflib_SObjectShareSelector + * + * @description Abstract selector for SObject Shares + * + * @author architect ir. Wilhelmus G.J. Velzeboer + * + * Copyright (c), W.G.J. Velzeboer, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above author notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +public abstract inherited sharing class fflib_SObjectShareSelector + extends fflib_SObjectSelector +{ + private String accessLevelFieldName + { + get + { + if (accessLevelFieldName == null) + { + accessLevelFieldName = fflib_SObjectShare.getAccessLevelFieldName(getSObjectType2()); + } + return accessLevelFieldName; + } + private set; + } + private String parentIdFieldName + { + get + { + if (parentIdFieldName == null) + { + parentIdFieldName = fflib_SObjectShare.getParentIdFieldName(getSObjectType2()); + } + return parentIdFieldName; + } + private set; + } + private String rowCauseFieldName = 'RowCause'; + private String userOrGroupIdName = 'UserOrGroupId'; + private List sObjectFieldList + { + get + { + if (sObjectFieldList == null) + { + SObjectType sObjectType = getSObjectType2(); + fflib_SObjectDescribe sObjectDescribe = fflib_SObjectDescribe.getDescribe(sObjectType); + sObjectFieldList = new List + { + fflib_SObjectShare.getIdField(sObjectType), + fflib_SObjectShare.getAccessLevelField(sObjectType), + fflib_SObjectShare.getParentIdField(sObjectType), + fflib_SObjectShare.getRowCauseField(sObjectType), + fflib_SObjectShare.getUserOrGroupIdField(sObjectType) + }; + } + return sObjectFieldList; + } + private set; + } + + public List getSObjectFieldList() + { + return sObjectFieldList; + } + + protected List selectShareByParentId(Set parentIds) + { + return Database.query( + newQueryFactory() + .setCondition(parentIdFieldName + ' IN :parentIds') + .toSOQL()); + } + + protected List selectShareByParentId(Set parentIds, Set userOrGroupIds) + { + return Database.query( + newQueryFactory() + .setCondition(parentIdFieldName + ' IN :parentIds AND ' + userOrGroupIdName + ' IN :userOrGroupIds') + .toSOQL()); + } + + protected List selectShareByParentId(Set parentIds, Set userOrGroupIds, Set accessLevels) + { + return Database.query( + newQueryFactory() + .setCondition(parentIdFieldName + ' IN :parentIds AND ' + + userOrGroupIdName + ' IN :userOrGroupIds AND ' + + accessLevelFieldName + ' IN :accessLevels') + .toSOQL()); + } + + protected List selectShareByParentId(Set parentIds, Set rowCauses) + { + return Database.query( + newQueryFactory() + .setCondition(parentIdFieldName + ' IN :parentIds AND ' + rowCauseFieldName + ' IN :rowCauses') + .toSOQL()); + } +} \ No newline at end of file diff --git a/sfdx-source/apex-extensions/main/default/classes/selectors/fflib_SObjectShareSelector.cls-meta.xml b/sfdx-source/apex-extensions/main/default/classes/selectors/fflib_SObjectShareSelector.cls-meta.xml new file mode 100644 index 0000000..f928c8e --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/selectors/fflib_SObjectShareSelector.cls-meta.xml @@ -0,0 +1,5 @@ + + + 53.0 + Active + diff --git a/sfdx-source/apex-extensions/main/default/classes/utils/fflib_SObjectShare.cls b/sfdx-source/apex-extensions/main/default/classes/utils/fflib_SObjectShare.cls new file mode 100644 index 0000000..0838479 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/utils/fflib_SObjectShare.cls @@ -0,0 +1,294 @@ +/** + * File Name: fflib_SObjectShare + * + * @author architect ir. Wilhelmus G.J. Velzeboer + * + * Copyright (c), W.G.J. Velzeboer, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above author notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +public with sharing class fflib_SObjectShare +{ + private static final String ACCESS_LEVEL_EDIT = 'Edit'; + private static final String ACCESS_LEVEL_READ = 'Read'; + + /** + * Creates a Share record for the given userOrGroup to the parentId with the access level "Edit" + * + * @param sObjectType The SObjectType of the share to create + * @param parentId The parent objects Id + * @param userOrGroupId The Id of the user or group + * + * @return Return the created share + */ + public static SObject createEditShare( + SObjectType sObjectType, + Id parentId, + Id userOrGroupId) + { + return createShares(sObjectType, new Set{ parentId }, new Set{ userOrGroupId }, ACCESS_LEVEL_EDIT) + .get(0); + } + + /** + * Creates a Share record for each userOrGroup to the parentId with the access level "Edit" + * + * @param sObjectType The SObjectType of the share to create + * @param parentId The parent objects Id + * @param userOrGroupIds The Ids of the users or groups + * + * @return Returns a list of the created shares + */ + public static List createEditShares( + SObjectType sObjectType, + Id parentId, + Set userOrGroupIds) + { + return createShares(sObjectType, new Set{ parentId }, userOrGroupIds, ACCESS_LEVEL_EDIT); + } + + /** + * Creates a Share record for each userOrGroup for each parentId with the access level "Edit" + * + * @param sObjectType The SObjectType of the share to create + * @param parentIds The parents object Id + * @param userOrGroupIds The Id of the user or group + * + * @return Returns a list of the created shares + */ + public static List createEditShares( + SObjectType sObjectType, + Set parentIds, + Set userOrGroupIds) + { + return createShares(sObjectType, parentIds, userOrGroupIds, ACCESS_LEVEL_EDIT); + } + + /** + * Creates a Share record for the given userOrGroup to the parentId with the access level "Read" + * + * @param sObjectType The SObjectType of the share to create + * @param parentId The parent objects Id + * @param userOrGroupId The Id of the user or group + * + * @return Return the created share + */ + public static SObject createReadShare( + SObjectType sObjectType, + Id parentId, + Id userOrGroupId) + { + return createShares(sObjectType, new Set{ parentId }, new Set{ userOrGroupId }, ACCESS_LEVEL_READ) + .get(0); + } + + /** + * Creates a Share record for each userOrGroup to the parentId with the access level "Read" + * + * @param sObjectType The SObjectType of the share to create + * @param parentId The parent objects Id + * @param userOrGroupIds The Ids of the users or groups + * + * @return Returns a list of the created shares + */ + public static List createReadShares( + SObjectType sObjectType, + Id parentId, + Set userOrGroupIds) + { + return createShares(sObjectType, new Set{ parentId }, userOrGroupIds, ACCESS_LEVEL_READ); + } + + /** + * Creates a Share record for each userOrGroup for each parentId with the access level "Read" + * + * @param sObjectType The SObjectType of the share to create + * @param parentIds The parents object Id + * @param userOrGroupIds The Id of the user or group + * + * @return Returns a list of the created shares + */ + public static List createReadShares( + SObjectType sObjectType, + Set parentIds, + Set userOrGroupIds) + { + return createShares(sObjectType, parentIds, userOrGroupIds, ACCESS_LEVEL_READ); + } + + /** + * Creates a Share record for each userOrGroup for each parentId + * + * @param sObjectType The SObjectType of the share to create + * @param parentIds The parents object Id + * @param userOrGroupIds The Id of the user or group + * @param accessLevel The access level "Read" / "Edit" / "None" + * + * @return Returns a list of the created shares + */ + public static List createShares( + SObjectType sObjectType, + Set parentIds, + Set userOrGroupIds, + String accessLevel) + { + String parentIdFieldName = getParentIdFieldName(sObjectType); + String accessLevelFieldName = getAccessLevelFieldName(sObjectType); + SObjectType sObjectTypeShare = getSObjectTypeShare(sObjectType); + + List results = new List(); + for (Id parentId : parentIds) + { + for (Id userOrGroupId : userOrGroupIds) + { + SObject result = sObjectTypeShare.newSObject(); + result.put(parentIdFieldName, parentId); + result.put( 'UserOrGroupId', userOrGroupId ); + result.put(accessLevelFieldName, accessLevel); + result.put( 'RowCause', 'Manual' ); + results.add(result); + } + } + return results; + } + + /** + * Gets the SObjectField for the Id field of the given SObjectType + * + * @param sObjectType The SObjectType to get its Id field + * + * @return Returns the Id.SObjectField + */ + public static SObjectField getIdField(SObjectType sObjectType) + { + return getsObjectField(fflib_SObjectDescribe.getDescribe(sObjectType).getFields(), 'Id'); + } + + /** + * Gets the name of the AccessLevel field of the given SObjectType + * + * @param sObjectType The SObjectType to get its AccessLevel field + * + * @return Returns the AccessLevel name e.g. "AccessLevel" or "AccountAccessLevel + */ + public static String getAccessLevelFieldName(SObjectType sObjectType) + { + String sObjectName = sObjectType.getDescribe().getName(); + return (isCustom(sObjectName) ? '' : sObjectName.substringBefore('Share')) + 'AccessLevel'; + } + + /** + * Gets the SObjectField for the AccessLevel field of the given SObjectType + * + * @param sObjectType The SObjectType to get its AccessLevel field + * + * @return Returns the xxxAccessLevel.SObjectField + */ + public static SObjectField getAccessLevelField(SObjectType sObjectType) + { + return getsObjectField( + fflib_SObjectDescribe.getDescribe(sObjectType).getFields(), + getAccessLevelFieldName(sObjectType)); + } + + /** + * Gets the name of the ParentId field of the given SObjectType + * + * @param sObjectType The SObjectType to get its parent Id field + * + * @return Returns the parent field name e.g. "ParentId" or "AccountId" + */ + public static String getParentIdFieldName(SObjectType sObjectType) + { + String sObjectName = sObjectType.getDescribe().getName(); + return (isCustom(sObjectName) ? 'Parent' : sObjectName.substringBefore('Share')) + 'Id'; + } + + /** + * Gets the SObjectField for the ParentId field of the given SObjectType + * + * @param sObjectType The SObjectType to get its parent Id field + * + * @return Returns the xxxId.SObjectField e.g. ParentId.SObjectField or AccountId.SObjectField + */ + public static SObjectField getParentIdField(SObjectType sObjectType) + { + return getsObjectField( + fflib_SObjectDescribe.getDescribe(sObjectType).getFields(), + getParentIdFieldName(sObjectType)); + } + + /** + * Gets the SObjectField for the RowCause field of the given SObjectType + * + * @param sObjectType The SObjectType to get its RowCause field + * + * @return Returns the RowCause.SObjectField + */ + public static SObjectField getRowCauseField(SObjectType sObjectType) + { + return getsObjectField( + fflib_SObjectDescribe.getDescribe(sObjectType).getFields(), + 'RowCause'); + } + + /** + * Gets the SObjectField for the UserOrGroupId field of the given SObjectType + * + * @param sObjectType The SObjectType to get its UserOrGroupId field + * + * @return Returns the UserOrGroupId.SObjectField + */ + public static SObjectField getUserOrGroupIdField(SObjectType sObjectType) + { + return getsObjectField( + fflib_SObjectDescribe.getDescribe(sObjectType).getFields(), + 'UserOrGroupId'); + } + + private static SObjectField getsObjectField(fflib_SObjectDescribe.FieldsMap fields, String fieldName) + { + return fields.get(fieldName).getDescribe().getSobjectField(); + } + + private static SObjectType getSObjectTypeShare(SObjectType sObjectType) + { + String sObjectName = sObjectType.getDescribe().getName(); + + if (sObjectName.endsWith('Share')) return sObjectType; // is already a Share SObjectType + + // Try to construct the Share SObject from + if (sObjectName.endsWith('__c')) + return + fflib_SObjectDescribe.getDescribe(sObjectName.replace('__c', '__Share')) + .getDescribe().getSObjectType(); + + return fflib_SObjectDescribe.getDescribe(sObjectName + 'Share') + .getDescribe().getSObjectType(); + } + + private static Boolean isCustom(String sObjectName) + { + return sObjectName.endsWith('__Share') || sObjectName.endsWith('__c'); + } +} \ No newline at end of file diff --git a/sfdx-source/apex-extensions/main/default/classes/utils/fflib_SObjectShare.cls-meta.xml b/sfdx-source/apex-extensions/main/default/classes/utils/fflib_SObjectShare.cls-meta.xml new file mode 100644 index 0000000..f928c8e --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/utils/fflib_SObjectShare.cls-meta.xml @@ -0,0 +1,5 @@ + + + 53.0 + Active +