1

I am kind of new to the Trigger world of Salesforce and am having an issue figuring out how to update a few text fields whenever a Chatter File is uploaded to the record. Sounds pretty simple to me but I can't wrap my head around it.

Object: Subject__c
Fields need to update: Image1__c, Image2__c, Image3__c, Image4__c, Image5__c
Chatter File ID needed: ContentDocument.LatestPublishedVersion

The goal is that whenever someone uploads picture files of .jpg or .jpeg extension to the record via Chatter Files that these 5 fields get updated to have the ID of that image so we can than show it as a preview on the record page. I have the preview figured out but I can't figure out how to get the fields to update after the upload. Below is the code I have been playing around with now for a few weeks. Any help would be much appreciated as I am lost at this point. Thanks.

trigger Update_Image_Field_BPR2 on ContentDocumentLink (after insert, after update, before delete, after undelete){
    List<Subject__c> subList = new List<Subject__c>();
    Set<id> subIds = new Set<id>();
    for(ContentDocumentLink content : Trigger.IsDelete ? Trigger.old : Trigger.new){
        String parentObjId = content.LinkedEntityId;
        if(parentObjId.startsWith('a07')){
            subIds.add(content.LinkedEntityId);
        }
    }
    Map<id, Subject__c> subMap = new Map<id, Subject__c>([Select id, Image1__c, Image2__c, Image3__c, Image4__c, Image5__c from Subject__c Where Id in :subIds]); 
    List<ContentDocumentLink> docList = [SELECT ContentDocument.LatestPublishedVersionId FROM ContentDocumentLink 
            WHERE LinkedEntityId IN :subIds AND (ContentDocument.FileExtension = 'jpg' OR ContentDocument.FileExtension = 'jpeg' OR ContentDocument.FileExtension = 'png' 
            OR ContentDocument.FileExtension = 'gif')];
    //List<String> docIds = new List<String>(docMap.values());
    for(ContentDocumentLink content : Trigger.IsDelete ? Trigger.old : Trigger.new){
        String parentObjId = content.LinkedEntityId; 
        if(parentObjId.startsWith('a07')){
            Subject__c sub = subMap.get(content.LinkedEntityId);
            //ContentDocumentLink querymember = docMap.get(content.id);
            //String fullFileURL1 = querymember.ContentDocument.LatestPublishedVersionId;
            String fullFileURL1 = String.valueOf(docList[0].ContentDocument.LatestPublishedVersionId);
            String fullFileURL2 = String.valueOf(docList[1].ContentDocument.LatestPublishedVersionId);
            String fullFileURL3 = String.valueOf(docList[2].ContentDocument.LatestPublishedVersionId);
            String fullFileURL4 = String.valueOf(docList[3].ContentDocument.LatestPublishedVersionId);
            String fullFileURL5 = String.valueOf(docList[4].ContentDocument.LatestPublishedVersionId);
            if(!Trigger.IsDelete){
                sub.Image1__c = fullFileURL1;
                sub.Image2__c = fullFileURL2;
                sub.Image3__c = fullFileURL3;
                sub.Image4__c = fullFileURL4;
                sub.Image5__c = fullFileURL5;
            }
            subList.add(sub);
        }
    }

}

UPDATED: I got one text field to update using the above updated trigger. I am trying to figure out how to take a map, the one above called docMap, and iterate it into a loop or something so I can have it update the sub.Image1__c and other files as shown in the code.

UPDATED: Removed comments for easier reading. Also moved my SOQL out of the For Loop. Appreciate the feedback! Any other ideas about how to update the5 fields using the Map? Thanks.

  • 1
    You have some issues here - (1) trigger is not bulkified (you are doing soql inside of for loop; (2) if you are new to triggers, well worth starting on the right foot with a trigger framework that will organize your logic into cleaner bits (google on apex trigger framework) (3) use developer console to make sure your queries are correct (4) edit your post and get rid of commented out lines - they confuse the community – cropredy Feb 16 '16 at 21:17
  • crop1645, Thanks for the suggestions. I have updated the code based on your suggestion. Any ideas on how to update the 5 fields from a map? Thanks again! – Nathan Feb 16 '16 at 21:37
  • docs is not declared – cropredy Feb 16 '16 at 22:16
3

First off, I'll note that parentObjId.startsWith('a07') is a rather fragile way to check what type you're dealing with. I'd strongly reccomend changing to parentObjId.getSObjectType() == Subject__c.SObjectType. This will work in any other orgs you deploy this code to or if salesforce changes any implementation details.

As for iterating over a map there are two ways of doing this:

  1. Loop over the keys to the map. You can get these from the Map.keySet() method and do something like for(Id recordId:myMap.keySet(){ /* code */}
  2. Loop over the values directly. This is a bit faster if you don't need the key at the same time (which, since it's on the SObject you don't really here). use Map.values(), i.e. for(SObject record:myMap.values()){ /* code */}

    A final note that catch(Exception e){ System.debug('ERROR: '+ e);} is generally not a good thing to do in salesforce. Since the debug log is only generated if you've created a TraceFlag ahead of time (by having the developer console or via the debug UI) most of these issues will be silently discarded. It's better to either use SObject.addError(Exception) on all the records in the trigger scope or send an email to the admin so it's logged somewhere.

  • ca_peterson, thanks so much for the reply. I am trying to take the list called docList and take all the values and assign it to fullFileURL1, fullFileURL2, etc. Just the first 5. I changed it from a map to a list because I was told it was easier to work with. I updated the code above based on your recommendations and others which is good, I am not getting an error but nothing is happening when I test it out. My guess is the values are null. Any ideas? I will look into the parentobjId ideas as that looks cool. Thanks! – Nathan Feb 16 '16 at 22:30
  • @Nathan maps are an unordered collection, so the notion of "first" has no meaning to them. Lists being ordered are a much better fit for what you're doing. Did you try removing the catch and debug block? It's possible an exception is being thrown and unless you're looking carefully at the debug logs you aren't seeing it. Also, because this is an after trigger any chances you make to the Trigger.new/old collection won't be automatically saved like a before trigger. You'd need to use a before trigger or do an explicit update operation. – ca_peterson Feb 16 '16 at 22:32
  • Good call! I got the error below – Nathan Feb 16 '16 at 22:40
  • Error: There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger Update_Image_Field_BPR2 caused an unexpected exception, contact your administrator: Update_Image_Field_BPR2: execution of AfterInsert caused by: System.QueryException: Implementation restriction: ContentDocumentLink requires a filter by a single Id on ContentDocumentId or LinkedEntityId using the equals operator or multiple Id's using the IN operator.: Trigger.Update_Image_Field_BPR2: line 11, column 1". – Nathan Feb 16 '16 at 22:40
0

I figured out how to do this. Below is the code that finally worked. Thanks to all who helped.

trigger Update_Image_Field_BPR2 on ContentDocumentLink (after insert, after update, before delete, after undelete){
try{
    List<Subject__c> subList = new List<Subject__c>();
    List<Business__c> busList = new List<Business__c>();
    //Set of Subject__c Ids that we will iterate through
    Set<id> fileIds = new Set<id>();
    for(ContentDocumentLink content : Trigger.IsDelete ? Trigger.old : Trigger.new){
        Id parentObjId = content.LinkedEntityId;
        if(parentObjId.getSObjectType() == Subject__c.SObjectType || parentObjId.getSObjectType() == Business__c.SObjectType){
            fileIds.add(content.LinkedEntityId);
        }        
    }
    // Get the Subject__c id and Image1__c  for each Subject__c
    Map<id, Subject__c> subMap = new Map<id, Subject__c>([Select id, Image1__c, Image2__c, Image3__c, Image4__c, Image5__c 
                                                          from Subject__c Where Id in :fileIds]);  
    Map<id, Business__c> busMap = new Map<id, Business__c>([Select id, Image1__c, Image2__c, Image3__c, Image4__c, Image5__c 
                                                            from Business__c Where Id in :fileIds]);  
    Map<id, ContentDocumentLink> docMap = new Map<id, ContentDocumentLink>([SELECT ContentDocument.LatestPublishedVersionId 
                                                                            FROM ContentDocumentLink WHERE LinkedEntityId IN :fileIds
                                                                           AND (ContentDocument.FileExtension = 'jpg' OR ContentDocument.FileExtension = 'jpeg' 
                                                                                OR ContentDocument.FileExtension = 'png' OR ContentDocument.FileExtension = 'gif')]); 
    for(ContentDocumentLink content : Trigger.IsDelete ? Trigger.old : Trigger.new){
        Id parentObjId = content.LinkedEntityId;
        if(parentObjId.getSObjectType() == Business__c.SObjectType){
            Business__c bus = busMap.get(content.LinkedEntityId);
            ContentDocumentLink querymember = docMap.get(content.id);
            String fullFileURL = querymember.ContentDocument.LatestPublishedVersionId;
            system.debug(fullFileURL);
            if(!Trigger.IsDelete){
                If(bus.Image1__c == null){
                    bus.Image1__c = fullFileURL;
                }else{
                    if(bus.Image2__c == null){
                        bus.Image2__c = fullFileURL;
                    }else{
                        if(bus.Image3__c == null){
                            bus.Image3__c = fullFileURL;
                        }else{
                            if(bus.Image4__c == null){
                                bus.Image4__c = fullFileURL;
                            }else{
                                if(bus.Image5__c == null){
                                    bus.Image5__c = fullFileURL;    
                                }
                            }}}}}
            if(Trigger.IsDelete){
                If(bus.Image1__c == fullFileURL){
                    bus.Image1__c = null;
                }else{
                    if(bus.Image2__c == fullFileURL){
                        bus.Image2__c = null;
                    }else{
                        if(bus.Image3__c == fullFileURL){
                            bus.Image3__c = null;
                        }else{
                            if(bus.Image4__c == fullFileURL){
                                bus.Image4__c = null;
                            }else{
                                if(bus.Image5__c == fullFileURL){
                                    bus.Image5__c = null;    
                                }}}}}}
            busList.add(bus);
        }
        if(parentObjId.getSObjectType() == Subject__c.SObjectType){
            Subject__c sub = subMap.get(content.LinkedEntityId);
            ContentDocumentLink querymember = docMap.get(content.id);
            String fullFileURL = querymember.ContentDocument.LatestPublishedVersionId;
            system.debug(fullFileURL);
            if(!Trigger.IsDelete){
                If(sub.Image1__c == null){
                    sub.Image1__c = fullFileURL;
                }else{
                    if(sub.Image2__c == null){
                        sub.Image2__c = fullFileURL;
                    }else{
                        if(sub.Image3__c == null){
                            sub.Image3__c = fullFileURL;
                        }else{
                            if(sub.Image4__c == null){
                                sub.Image4__c = fullFileURL;
                            }else{
                                if(sub.Image5__c == null){
                                    sub.Image5__c = fullFileURL;    
                                }
                            }}}}}
            if(Trigger.IsDelete){
                If(sub.Image1__c == fullFileURL){
                    sub.Image1__c = null;
                }else{
                    if(sub.Image2__c == fullFileURL){
                        sub.Image2__c = null;
                    }else{
                        if(sub.Image3__c == fullFileURL){
                            sub.Image3__c = null;
                        }else{
                            if(sub.Image4__c == fullFileURL){
                                sub.Image4__c = null;
                            }else{
                                if(sub.Image5__c == fullFileURL){
                                    sub.Image5__c = null;    
                                }}}}}}
            subList.add(sub);
        }
    }
    if(subList != null && subList.size() > 0){update subList;}if(busList != null && busList.size() > 0){update busList;}} catch(Exception e){ System.debug('ERROR: '+ e);}
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.