1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
global without sharing class Batch_FixDocumentToFiles implements Database.Batchable<sObject>{
    // https://github.com/douglascayers/sfdc-convert-documents-to-files/tree/master/src/classes
    private Set<String> folderIds = new Set<String>();//Add by Li Jun 20230703 
    //Add by Gzw 20231030 Start
    public Batch_FixDocumentToFiles(Set<String> folderIds) {
        this.folderIds = folderIds;
    }
    global Database.QueryLocator start(Database.BatchableContext BC) {
        // String queryObject = 'SELECT Id, Name, OwnerId, ParentId, Parent.Name, Parent.Type, Body, CreatedDate, CreatedById FROM Attachment WHERE Parent.Type =:objectApiName AND CreatedDate >=:creStartDate AND CreatedDate <:creEndDate Order by CreatedDate ASC';
        // if(folderIds.size() > 0){
        //     queryObject = 'SELECT Id, Name, OwnerId, ParentId, Parent.Name, Parent.Type, Body, CreatedDate, CreatedById FROM Attachment WHERE ParentId in:parentIds';
        // }
 
        String sql = 'SELECT Id, Name, DeveloperName,Description, ContentType,Type,Body,Url,Keywords,FolderId, Folder.Name,Folder.DeveloperName,AuthorId,CreatedById, CreatedDate, LastModifiedById, LastModifiedDate  FROM  Document where FolderId in: folderIds ' ;
 
        if(System.Test.isRunningTest()){
            sql += ' limit 1';
        }
 
        return Database.getQueryLocator(sql);
    }
    global void execute(Database.BatchableContext BC, List<Document> scope) {
        Set<ID> documentIds = new Set<ID>();
        Set<ID> folderIds = new Set<ID>();
        for ( Document doc : scope ) {
            documentIds.add( doc.Id );
            folderIds.add( doc.FolderId );
        }
 
        Set<String> libraryNames = new Set<String>();
        Map<ID, Folder> foldersMap = new Map<ID, Folder>([ SELECT Id, Name, DeveloperName FROM Folder WHERE Id IN :folderIds ]);
        for ( Folder f : foldersMap.values() ) {
            // libraryNames.add( buildLibraryDeveloperName( f.Name ) );
            libraryNames.add( f.Name );
        }
 
        Map<ID, ContentWorkspace> librariesMap = new Map<ID, ContentWorkspace>([ SELECT Id, Name, DeveloperName FROM ContentWorkspace WHERE Name IN :libraryNames ]);
        Map<String, ContentWorkspace> libraryNamesMap = toMapByKeyField( ContentWorkspace.Name, librariesMap.values() );
 
        // Map<ID, ID> alreadyConvertedDocumentIdsMap = getAlreadyConvertedDocumentIdsMap( documentIds, librariesMap.keySet() );
 
        // todo add error handling and logging like in ConvertAttachmentsToFilesService.cls
        List<ContentVersion> newFileVersions = new List<ContentVersion>();
 
        for ( Document doc : scope ) {
 
            // todo log a skipped conversion result like attachment converter project
            // if ( alreadyConvertedDocumentIdsMap.containsKey( doc.Id ) ) {
            //     System.debug( 'Document has already been converted, skipping... ' + doc );
            //     continue;
            // }
 
            Folder f = foldersMap.get( doc.FolderId );
            // String libraryName = buildLibraryDeveloperName( f.DeveloperName );
            ContentWorkspace library = libraryNamesMap.get( f.Name );
 
            newFileVersions.add( new ContentVersion(
                // data fields
                VersionData = doc.Body,
                PathOnClient = '/' + doc.DeveloperName + '.' + doc.Type,
                Title = doc.Name,
                Description = doc.Description,
                FirstPublishLocationId = library.Id,
                TagCsv = doc.Keywords,
                // audit fields
                OwnerId = doc.AuthorId, // system requirement, owner and creator must be the same
                CreatedById = doc.AuthorId,
                CreatedDate = doc.CreatedDate,
                LastModifiedById = doc.LastModifiedById,
                LastModifiedDate = doc.LastModifiedDate
            ));
        }
        insert newFileVersions;
 
    }
 
    // private String buildLibraryDeveloperName( String folderDeveloperName ) {
    //     return 'Doc2File_' + folderDeveloperName;
    // }
    // public Map<ID, ID> getAlreadyConvertedDocumentIdsMap( Set<ID> documentIds, Set<ID> libraryIds ) {
 
    //     // map of old Document ids to new file ids
    //     Map<ID, ID> convertedDocumentIdsMap = new Map<ID, ID>();
 
    //     for ( List<ContentDocumentLink> links : [
    //         SELECT
    //             ContentDocument.LatestPublishedVersionId,
    //             ContentDocument.LatestPublishedVersion.Original_Record_ID__c
    //         FROM
    //             ContentDocumentLink
    //         WHERE
    //             LinkedEntityId IN :libraryIds
    //             AND
    //             ContentDocument.LatestPublishedVersion.Original_Record_ID__c IN :documentIds
    //     ]) {
 
    //         for ( ContentDocumentLink link : links ) {
 
    //             if ( link.ContentDocument != null && link.ContentDocument.LatestPublishedVersion != null ) {
 
    //                 if ( documentIds.contains( link.ContentDocument.LatestPublishedVersion.Original_Record_ID__c ) ) {
    //                     convertedDocumentIdsMap.put( link.ContentDocument.LatestPublishedVersion.Original_Record_ID__c, link.ContentDocument.LatestPublishedVersionId );
    //                 }
 
    //             }
 
    //         }
 
    //     }
 
    //     return convertedDocumentIdsMap;
    // }
    public static Map<String, ContentWorkspace> toMapByKeyField( SObjectField mapKeyField, List<ContentWorkspace> records ) {
 
        Map<String, ContentWorkspace> recordsMap = new Map<String, ContentWorkspace>();
 
        for ( ContentWorkspace record : records ) {
            String mapKey = String.valueOf( record.get( mapKeyField ) );
            recordsMap.put( mapKey, record );
        }
 
        return recordsMap;
    }
 
    global void finish(Database.BatchableContext BC) {
 
    }
}