[SalesForce] querying and creating folders/files from within a library

I have a library called Test, which has a folder in it called 123. The folder contains a single pdf file.

enter image description here

I'm able to successfully query that file using the following SOQL statement.

SELECT Id, Title, FileExtension FROM ContentFolderItem WHERE ParentContentFolderId IN (SELECT Id FROM ContentFolder WHERE Name = '123')

Is there anyway to add to this query the condition to include the library name Test?

I was able to create the library, folder, and upload the pdf using the UI. How can I do all that with apex?

This is what I've done in my test code, but I can't navigate the relationships of all the sObjects involved.

    // create Library
    System.runAs ( new User(Id = UserInfo.getUserId()) ) {
        ContentWorkspace cw = new ContentWorkspace();
        cw.Name = 'Test';

        insert cw;        
    }

    // creat file
    ContentVersion cv = new ContentVersion();
    cv.Title = 'dummy';
    cv.PathOnClient = 'dummy.pdf';
    cv.VersionData = EncodingUtil.base64Decode('test');

    insert cv;

     // create folder. There is no clear way to add this folder to a library using apex...
     ContentFolder f = new ContentFolder();
     f.Name = '123';

     insert f;

Then there needs to be some dml usage using ContentFolderItem and ContentFolderLink I believe…

After creating a folders, I've tried this code:

    ContentWorkspace cw = [SELECT Id FROM ContentWorkspace WHERE Name = 'Test'];


    Database.SaveResult[]  results = Database.insert(folders, true);

    List<ContentFolderLink> folderLinks = new List<ContentFolderLink>();

    for(Database.SaveResult r : results) {
        if(r.isSuccess()) {
            ContentFolderLink cfl = new ContentFolderLink();
            cfl.EnableFolderStatus = 'S';
            cfl.ParentEntityId = cw.Id;
            cfl.ContentFolderId = r.Id;

            folderLinks.add(cfl);    
        }
    }

put I get a bunch of Field is not writeable errors.

Best Answer

I ran into a similar issue and turns out that there are some additional objects that support linking documents into a specific folder.

The ContentDocumentLink will share the documents to the workspace and automatically create ContentFolderMember records. In order to push those records into a sub-folder within the workspace, you have to query and update those existing records. Trying to create new ContentFolderMember records will result in a duplicate error.

To put it all together, it would look something like this:

@testSetup
private static void createTestData() {
    ContentWorkspace testWorkspace = new ContentWorkspace(Name='TEST CLASS', DeveloperName='TEST_CLASS');
    insert testWorkspace;
}

@isTest
private static void testGetFilesList(){
    ContentWorkspace testWorkspace = [Select Id from ContentWorkspace where Name = 'TEST CLASS'];

    ContentFolder workspaceFolder = [Select Id from ContentFolder where Name =: testWorkspace.Id];

    ContentFolder testFolderRecord = new ContentFolder(Name='TEST FOLDER', ParentContentFolderId=workspaceFolder.Id);
    insert testFolderRecord;

    List<ContentVersion> contentVersions = new List<ContentVersion>();

    for(Integer i = 1; i <= 12; i++) {
        String fileExtension = '';
        Switch on i {
            when 1 {
                fileExtension='csv';
            }
            when 2 {
                fileExtension='jpg';
            }
            when 3 {
                fileExtension='gif';
            }
            when 4 {
                fileExtension='tiff';
            }
            when 5 {
                fileExtension='ppt';
            }
            when 6 {
                fileExtension='xls';
            }
            when 7 {
                fileExtension='xlsx';
            }
            when 8 {
                fileExtension='doc';
            }
            when 9 {
                fileExtension='docx';
            }
            when 10 {
                fileExtension='pdf';
            }
            when 11 {
                fileExtension='pptx';
            }
            when else {
                fileExtension='json';
            }
        }

        ContentVersion cv = new ContentVersion();
        cv.title = 'test content'+i;        
        cv.VersionData = Blob.valueOf('Unit Test Attachment Body'+i);
        cv.PathOnClient = 'test content'+i+'.'+fileExtension;
        contentVersions.add(cv);
    }

    insert contentVersions;

    List<ContentDocumentLink> documentLinks = new List<ContentDocumentLink>();
    List<ContentFolderMember> folderMembers = new List<ContentFolderMember>();

    for(ContentVersion cv : [Select Id, ContentDocumentId from ContentVersion]) {
        ContentDocumentLink cdl = new ContentDocumentLink();
        cdl.ContentDocumentId = cv.ContentDocumentId;
        cdl.LinkedEntityId = testWorkspace.Id;   
        cdl.Sharetype = 'I';
        documentLinks.add(cdl);
    }

    insert documentLinks;

    for(ContentFolderMember cfm : [Select Id, ChildRecordId, ParentContentFolderId
                                   from ContentFolderMember
                                   where ParentContentFolderId =: workspaceFolder.Id]) {
        cfm.ParentContentFolderId = testFolderRecord.Id;
        folderMembers.add(cfm);
    }

    update folderMembers;
}

(You can ignore the file extension piece, just optional to mimic adding different types of files)

This answer also provides some context: Upload File in ContentFolder

Related Topic