Find your content:

Search form

You are here

In a trigger, telling the difference between a new Chatter File and a Link to an Existing one


I like using Chatter Files for Attachments because they are prettier and searchable. The downside is that, when you add one to an Opporutunity, you don't see it as an Attachment on the Account like an old-skool Attachment would.

So I am working on a trigger where, if a user posts a Chatter File to an Opportunity, it also links it up to the Account. Sample code is below. I am successfully checking for it being a Chatter File (ContentPost) and only running when linked to an Opportunity, but the trigger runs whether I am adding a new file and also if I am associating an existing file to an Opportunity.

Any ideas how to determine whether the ContentPost is using a new Chatter File or an Existing one?

for (FeedItem f: fis){

    String parentIdString = String.valueOf(f.parentId);

    if (parentIdString.startsWith(Opportunity.sObjectType.getDescribe().getKeyPrefix()) && f.type == 'ContentPost'){
        Opportunity o = [select id, accountId from Opportunity where id = :f.ParentId limit 1][0];
        if(o.AccountId != null){
            FeedItem newFI = new FeedItem();
                newFI.Type = 'ContentPost';
                newFI.RelatedRecordId = f.RelatedRecordId;
                newFI.ParentId = o.AccountId;
                newFI.title = f.title;
            insert newFI;



NOTE: I am already aware of the issue with querying and DML in the loop. I will fix that later. I am mostly concerned with getting the scenario correctly handled.

Thanks, StackExchange!

Attribution to: hemmeter

Possible Suggestion/Solution #1

Are you writing your trigger on a FeedItem? If so, you should be able to leverage the after insert parameter to only have the trigger get invoked on creation.

trigger FeedItem_afterInsert on FeedItem (after insert)
    //define list of FeedItems connected to Account to create
    List<FeedItem> feedItemsToInsert = new List<FeedItem>();
    for (FeedItem f : [SELECT Id, RelatedRecordId FROM FeedItem WHERE Id =:])
        //check if Id record ID matches an opportunity. If so, do work

    insert feedItemsToInsert;

Attribution to: Michael Welburn

Possible Suggestion/Solution #2

I figured it out and blogged about it at my blog. The approach is to...

  • Create an AFTER INSERT trigger on FeedItem
  • Call an @future event that only works for new ContentPosts
  • The new file is linked to via the RelatedRecordId field on the FeedItem
  • Gather the IDs of other places this file should be linked be new ContentPosts.
  • Eliminate IDs that are already linked to the file
  • Create new FeedItems

The blog post has all the code. There are some other good best practices in there for wrapped @future calls in triggers and it uses the technique to prevent recursion of a trigger.

Attribution to: hemmeter

Possible Suggestion/Solution #3

I think I have come up with a better approach. However, there is one issue that I read was a bug getting fixed in Winter 13. We'll see about that.

The new approach is not to rely on Create Dates. That seemed a little hackish (in a bad way) anyway.

Instead, the new approach is to trigger on AFTER INSERT for FeedItem, use the RelatedRecordId value to query for ContentVersion and then use the ContentVersion.ContentDocumentId to query ContentDocumentLink. ContentDocumentLink is the table holding the linkage between a piece of Content and records.

The code will then use the records that content is already linked to and compare that with IDs we potentially want to link to (e.g. the account for an Opportunity, the contact and the account from a Case, etc.) For any IDs where there is no linkage, we'll create one by adding a new FeedItem record against that ID.

This approach seems clean. The only thing stopping it from working now is that the ContentVersion query never comes up with any records even though I know the records are there. I found some reference somewhere that this is a bug and is being fixed.

Thus, I'll wait for my Sandbox to be updated to Winter 13 and, when it is, I'll see if it's fixed. If so, I'll deploy after Winter 13 comes out.

Attribution to: hemmeter

Possible Suggestion/Solution #4

From my analysis, the best I can think of is to compare the following 3 dates either to be the same or maybe within a practical range of each other (1 second?):

  • Create Date on FeedItem
  • Create Date on ContentVersion (obtained by querying it using FeedItem.RelatedRecordId)
  • Create Date on ContentDocument (obtained by querying it using ContentVersion.ContentDocumentId)

Thoughts? Wish there was a flag I could check, but this seems to be the only way I can find.

Attribution to: hemmeter
This content is remixed from stackoverflow or stackexchange. Please visit

My Block Status

My Block Content