public void UpdateFolderDescriptions(Screen screen) { var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>(); EntityHelper entityHelper = new EntityHelper(this); BoxFolderCache screenFolderInfo = FoldersByScreen.Select(screen.ScreenID); foreach (BoxFolderCache boxFolderCache in FoldersByParentFolderID.Select(screenFolderInfo.FolderID)) { object row = entityHelper.GetEntityRow(boxFolderCache.RefNoteID, true); if (row != null) { var description = GetFolderDescriptionForEntityRow(row); try { BoxUtils.UpdateFolderDescription(tokenHandler, boxFolderCache.FolderID, description).Wait(); } catch (AggregateException ae) { ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) => { // Folder no longer exist on Box - it may have been deleted on purpose by the user screenFolderInfo = FoldersByScreen.Delete(boxFolderCache); }); } } } Actions.PressSave(); }
protected virtual void moveFolders() { var fileHandlerGraph = PXGraph.CreateInstance <FileHandler>(); var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>(); PXLongOperation.StartOperation(this, () => { EntityHelper entityHelper = new EntityHelper(this); var screenFolderCache = (BoxFolderCache)fileHandlerGraph.FoldersByScreen.Select(Screens.Current.ScreenID); var list = new List <BoxUtils.FileFolderInfo>(); //For each subfolders of a screen found on box server try { list = BoxUtils.GetFolderList(tokenHandler, screenFolderCache.FolderID, (int)BoxUtils.RecursiveDepth.FirstSubLevel).Result; } catch (AggregateException ae) { ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) => { ScreenUtils.TraceAndThrowException(Messages.BoxFolderNotFoundRunSynchAgain, screenFolderCache.FolderID); }); } foreach (var folder in list) { //If folder has a RefNoteID, it contains files and might need to be moved BoxFolderCache bfc = (BoxFolderCache)fileHandlerGraph.FoldersByFolderID.Select(folder.ID); if (bfc != null && bfc.RefNoteID.HasValue) { string presumedParentFolderID = screenFolderCache.FolderID; if (fileHandlerGraph.FieldsGroupingByScreenID.Select(Screens.Current.ScreenID).Any()) { presumedParentFolderID = fileHandlerGraph.GetOrCreateSublevelFolder(tokenHandler, Screens.Current.ScreenID, screenFolderCache.FolderID, bfc.RefNoteID.Value, false); } //if nested under the wrong folder if (presumedParentFolderID != null && folder.ParentFolderID != presumedParentFolderID) { try { BoxUtils.MoveFolder(tokenHandler, folder.ID, presumedParentFolderID).Wait(); bfc.ParentFolderID = presumedParentFolderID; fileHandlerGraph.FoldersByFolderID.Update(bfc); fileHandlerGraph.Actions.PressSave(); } catch (AggregateException ae) { ScreenUtils.HandleAggregateException(ae, HttpStatusCode.Conflict, (exception) => { //Skip this folder if a name conflict happens }); continue; } } } } }); }
public void SynchronizeScreen(Screen screen, BoxUtils.FileFolderInfo rootFolder, bool forceSync) { string folderName = string.Format("{0} ({1})", (object)BoxUtils.CleanFileOrFolderName(screen.Name), (object)screen.ScreenID); BoxFolderCache screenFolderInfo = FoldersByScreen.Select(screen.ScreenID); BoxUtils.FileFolderInfo folderInfo = null; var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>(); if (screenFolderInfo != null) { try { folderInfo = BoxUtils.GetFolderInfo(tokenHandler, screenFolderInfo.FolderID).Result; } catch (AggregateException ae) { ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) => { // Folder no longer exist on Box - it may have been deleted on purpose by the user. Remove it from cache so it is recreated on the next run. screenFolderInfo = FoldersByScreen.Delete(screenFolderInfo); Actions.PressSave(); throw new PXException(Messages.BoxFolderNotFoundRunSynchAgain, screenFolderInfo.ScreenID, exception); }); } } if (folderInfo == null) { // Folder wasn't found, try finding it by name in the root folder. folderInfo = BoxUtils.FindFolder(tokenHandler, rootFolder.ID, folderName).Result; } if (folderInfo == null) { // Folder doesn't exist at all - create it folderInfo = BoxUtils.CreateFolder(tokenHandler, folderName, rootFolder.ID).Result; } if (screenFolderInfo == null) { screenFolderInfo = (BoxFolderCache)FoldersByScreen.Cache.CreateInstance(); screenFolderInfo.FolderID = folderInfo.ID; screenFolderInfo.ParentFolderID = folderInfo.ParentFolderID; screenFolderInfo.ScreenID = screen.ScreenID; screenFolderInfo.LastModifiedDateTime = null; //To force initial sync screenFolderInfo = FoldersByScreen.Insert(screenFolderInfo); Actions.PressSave(); } // We don't synchronize the miscellaneous files folder, since we can't easily identify the corresponding NoteID from folder if (screen.ScreenID != FileHandler.MiscellaneousFolderScreenId && (forceSync || screenFolderInfo.LastModifiedDateTime != folderInfo.ModifiedAt)) { SynchronizeFolderContentsWithScreen(screenFolderInfo.ScreenID, screenFolderInfo.FolderID, forceSync); screenFolderInfo.LastModifiedDateTime = folderInfo.ModifiedAt; FoldersByScreen.Update(screenFolderInfo); Actions.PressSave(); } }
private BoxUtils.FileFolderInfo GetOrCreateActivityFolder(Guid?refNoteID, UserTokenHandler tokenHandler, object entityRow, object activityRefNoteID) { //Save an activity related file into the record's activity folder var activityRefNoteGuid = Guid.Parse(activityRefNoteID.ToString()); //Get or create record folder string folderID = GetOrCreateBoxFolderForNoteID(activityRefNoteGuid); BoxFolderCache recordFolderCache = FoldersByFolderID.Select(folderID); //Get or create Activities folder BoxUtils.FileFolderInfo activityFolderInfo = null; if (string.IsNullOrEmpty(recordFolderCache.ActivityFolderID)) { // Create Activities folder and update cache for future reference. activityFolderInfo = GetOrCreateFolder(tokenHandler, recordFolderCache.FolderID, null, null, Messages.ActivitiesFolderName); recordFolderCache.ActivityFolderID = activityFolderInfo.ID; FoldersByFolderID.Update(recordFolderCache); Actions.PressSave(); } else { try { // Folder was found in BoxFolderCache, retrieve it by ID activityFolderInfo = BoxUtils.GetFolderInfo(tokenHandler, recordFolderCache.ActivityFolderID).Result; } catch (AggregateException ae) { ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) => { using (new PXConnectionScope()) { // Delete entry from BoxFolderCache so that it gets created again. recordFolderCache.ActivityFolderID = null; FoldersByNote.Update(recordFolderCache); Actions.PressSave(); } throw new PXException(Messages.BoxFolderNotFoundTryAgain, recordFolderCache.FolderID, exception); }); } } //Get/Create activityRecord folder string folderName = GetFolderNameForActivityRow(entityRow); return(GetOrCreateFolder(tokenHandler, activityFolderInfo.ID, entityRow, refNoteID, folderName)); }
private BoxUtils.FileFolderInfo GetOrCreateFolder(UserTokenHandler tokenHandler, string parentFolderID, object entityRow, Guid?refNoteID, string folderName) { try { BoxUtils.FileFolderInfo folderInfo = BoxUtils.FindFolder(tokenHandler, parentFolderID, folderName).Result; if (folderInfo == null) { // Folder doesn't exist on Box, create it. var description = entityRow != null?GetFolderDescriptionForEntityRow(entityRow) : string.Empty; folderInfo = BoxUtils.CreateFolder(tokenHandler, folderName, parentFolderID, description).Result; } if (!FoldersByFolderID.Select(folderInfo.ID).Any()) { // Store the folder info in our local cache for future reference BoxFolderCache bfc = (BoxFolderCache)FoldersByFolderID.Cache.CreateInstance(); bfc.FolderID = folderInfo.ID; bfc.ParentFolderID = folderInfo.ParentFolderID; bfc.RefNoteID = refNoteID; bfc.LastModifiedDateTime = null; // To force initial sync of Box file list with record file ilst bfc = FoldersByFolderID.Insert(bfc); } return(folderInfo); } catch (AggregateException ae) { ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, (exception) => { using (new PXConnectionScope()) { var bfc = FoldersByFolderID.Cache.CreateInstance() as BoxFolderCache; bfc.FolderID = parentFolderID; FoldersByFolderID.Delete(bfc); Actions.PressSave(); } throw (new PXException(string.Format(Messages.BoxFolderNotFoundTryAgain, parentFolderID), exception)); }); return(null); } }
private void SynchronizeFolderContentsWithScreen(string screenID, string folderID, bool isForcingSync) { // Retrieve top-level folder list var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>(); List <BoxUtils.FileFolderInfo> boxFolderList = new List <BoxUtils.FileFolderInfo>(); if (FieldsGroupingByScreenID.Select(screenID).Any()) { boxFolderList = BoxUtils.GetFolderList(tokenHandler, folderID, (int)BoxUtils.RecursiveDepth.FirstSubLevel).Result; boxFolderList = boxFolderList.Where(x => x.Name.Contains("\\")).ToList(); } else { boxFolderList = BoxUtils.GetFolderList(tokenHandler, folderID, (int)BoxUtils.RecursiveDepth.NoDepth).Result; } foreach (BoxUtils.FileFolderInfo boxFolderInfo in boxFolderList) { BoxFolderCache bfc = FoldersByFolderID.Select(boxFolderInfo.ID); if (bfc != null) { //Make sure NoteDoc still exists NoteDoc nd = NoteDocs.Select(bfc.RefNoteID); if (nd == null) { //NoteDoc can't be found; this is likely a file coming from a record that was deleted. //Since an existing folder may be renamed to something which exists, we want to force system to treat it as if it was a new folder FoldersByFolderID.Delete(bfc); bfc = null; } } if (bfc == null) { // We've never seen this folder; sync it Guid?refNoteID; if (screenID == ActivityMaintScreenId) { //Activity folders use custom naming defined in GetFolderNameForActivityRow() - just look for GUID inside it. refNoteID = ExtractGuidFromString(boxFolderInfo.Name); } else { refNoteID = FindMatchingNoteIDForFolder(screenID, boxFolderInfo.Name); } if (refNoteID == null) { // User may have created some folder manually with a name not matching to any record, or record // may have been deleted in Acumatica. We can safely ignore it, but let's write to trace. PXTrace.WriteWarning(string.Format("No record found for folder {0} (screen {1}, ID {2})", boxFolderInfo.Name, screenID, boxFolderInfo.ID)); continue; } bfc = (BoxFolderCache)FoldersByNote.Select(refNoteID); if (bfc != null) { // A folder existed before for this record; clear the previous entry for this refNoteID FoldersByNote.Delete(bfc); } // Store folder in cache for future reference bfc = (BoxFolderCache)FoldersByFolderID.Cache.CreateInstance(); bfc.FolderID = boxFolderInfo.ID; bfc.ParentFolderID = boxFolderInfo.ParentFolderID; bfc.RefNoteID = refNoteID; bfc.LastModifiedDateTime = null; //To force initial sync bfc = FoldersByFolderID.Insert(bfc); } if (isForcingSync || bfc.LastModifiedDateTime != boxFolderInfo.ModifiedAt) { RefreshRecordFileList(screenID, boxFolderInfo.Name, boxFolderInfo.ID, bfc.RefNoteID, isForcingSync); bfc.LastModifiedDateTime = boxFolderInfo.ModifiedAt; FoldersByFolderID.Update(bfc); PXContext.SetSlot <bool>("BoxDisableLoad", true); try { Actions.PressSave(); } finally { PXContext.SetSlot <bool>("BoxDisableLoad", false); } } } }
public void RefreshRecordFileList(string screenID, string folderName, string folderID, Guid?refNoteID, bool isForcingSync) { var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>(); //Get list of files contained in the record folder. RecurseDepth=0 will retrieve all subfolders List <BoxUtils.FileFolderInfo> boxFileList = BoxUtils.GetFileList(tokenHandler, folderID, (int)BoxUtils.RecursiveDepth.Unlimited).Result; // Remove files from cache if they don't exist on Box server foreach (PXResult <BoxFileCache, UploadFileRevisionNoData, UploadFile, NoteDoc> result in FilesByNoteID.Select(refNoteID)) { BoxUtils.FileFolderInfo boxFile = boxFileList.FirstOrDefault(f => f.ID == ((BoxFileCache)result).FileID); if (boxFile == null) { //File was deleted FilesByNoteID.Delete(result); UploadFiles.Delete(result); UploadFileRevisions.Delete(result); NoteDocs.Delete(result); } else { // File still exists, remove it from in-memory list // so we don't process it as a new file in the next loop boxFileList.Remove(boxFile); } } // Remove any files/folders coming from activities stored beneath the current record, they've been processed above var filesFoundOnlyOnServer = boxFileList.Where(x => !x.Name.StartsWith(Messages.ActivitiesFolderName)).ToList(); //Check for underlying activities records BoxFolderCache currentFolder = FoldersByFolderID.Select(folderID); if (currentFolder != null && boxFileList.Any(x => x.Name.StartsWith(Messages.ActivitiesFolderName))) { // If nullOrEmpty, Folder may have been created manually if (string.IsNullOrEmpty(currentFolder.ActivityFolderID)) { //Find actual folder ID and save in BoxFolderCache's ActivityFolderID field BoxUtils.FileFolderInfo activityFolderinfo = BoxUtils.FindFolder(tokenHandler, folderID, Messages.ActivitiesFolderName).Result; if (activityFolderinfo != null) { currentFolder.ActivityFolderID = activityFolderinfo?.ID; FoldersByFolderID.Update(currentFolder); } } if (currentFolder.ActivityFolderID != null) { SynchronizeFolderContentsWithScreen(ActivityMaintScreenId, currentFolder.ActivityFolderID, isForcingSync); } } //Remaining files aren't found in cache but are in Box server. if (filesFoundOnlyOnServer.Any()) { if (refNoteID == null) { // User may have created some folder manually with a name not matching to any record, or record // may have been deleted in Acumatica. We can safely ignore it, but let's write to trace. PXTrace.WriteWarning(string.Format("No record found for folder {0} (screen {1}, ID {2})", folderName, screenID, folderID)); return; } UploadFileMaintenance ufm = PXGraph.CreateInstance <UploadFileMaintenance>(); ufm.IgnoreFileRestrictions = true; ufm.RowInserting.AddHandler <UploadFileRevision>(delegate(PXCache sender, PXRowInsertingEventArgs e) { ((UploadFileRevision)e.Row).BlobHandler = Guid.NewGuid(); }); //Add files to the caches foreach (BoxUtils.FileFolderInfo boxFile in filesFoundOnlyOnServer) { ufm.Clear(); string fileName = string.Format("{0}\\{1}", folderName, boxFile.Name.Replace(Path.GetInvalidPathChars(), ' ')); FileInfo fileInfo = ufm.GetFileWithNoData(fileName); Guid? blobHandlerGuid; if (fileInfo == null) { fileInfo = new FileInfo(fileName, null, new byte[0]); //The SaveFile call will trigger a Load() on the BoxBlobStorageProvider which can be skipped PXContext.SetSlot <bool>("BoxDisableLoad", true); try { if (!ufm.SaveFile(fileInfo)) { throw new PXException(Messages.ErrorAddingFileSaveFileFailed, fileName); } } finally { PXContext.SetSlot <bool>("BoxDisableLoad", false); } if (!fileInfo.UID.HasValue) { throw new PXException(Messages.ErrorAddingFileUIDNull, fileName); } UploadFileMaintenance.SetAccessSource(fileInfo.UID.Value, null, screenID); NoteDoc noteDoc = (NoteDoc)NoteDocs.Cache.CreateInstance(); noteDoc.NoteID = refNoteID; noteDoc.FileID = fileInfo.UID; NoteDocs.Insert(noteDoc); blobHandlerGuid = ufm.Revisions.Current.BlobHandler; } else { //File already exists in the database, retrieve BlobHandler if (!fileInfo.UID.HasValue) { throw new PXException(Messages.GetFileWithNoDataReturnedUIDNull, fileName); } blobHandlerGuid = GetBlobHandlerForFileID(fileInfo.UID.Value); //Clear old references of this blob handler from cache; it will be reinserted with up-to-date info var bfcOrphan = (BoxFileCache)FilesByBlobHandler.Select(blobHandlerGuid); if (bfcOrphan != null) { FilesByBlobHandler.Delete(bfcOrphan); } //Update NoteDoc entry if existing file was moved to new NoteID or create it if not there NoteDoc nd = (NoteDoc)NoteDocsByFileID.Select(fileInfo.UID); if (nd == null) { nd = (NoteDoc)NoteDocs.Cache.CreateInstance(); nd.NoteID = refNoteID; nd.FileID = fileInfo.UID; NoteDocs.Insert(nd); } else if (nd.NoteID != refNoteID) { nd.NoteID = refNoteID; NoteDocs.Update(nd); } } var bfc = (BoxFileCache)FilesByBlobHandler.Cache.CreateInstance(); bfc.BlobHandler = blobHandlerGuid; bfc.FileID = boxFile.ID; bfc.ParentFolderID = boxFile.ParentFolderID; bfc = FilesByBlobHandler.Insert(bfc); } } }
public Guid SaveFileToBoxAndUpdateFileCache(byte[] data, PXBlobStorageContext saveContext) { BoxUtils.FileFolderInfo boxFile = null; Guid blobHandlerGuid = Guid.NewGuid(); var tokenHandler = PXGraph.CreateInstance <UserTokenHandler>(); if (saveContext == null || saveContext.FileInfo == null || !saveContext.NoteID.HasValue) { var fileName = string.Empty; if (saveContext?.FileInfo?.Name == null) { fileName = blobHandlerGuid.ToString(); } else { fileName = BoxUtils.CleanFileOrFolderName(saveContext.FileInfo.Name); fileName = $"{Path.GetFileNameWithoutExtension(fileName)} ({blobHandlerGuid.ToString()}){Path.GetExtension(fileName)}"; } //We don't know on which screen this file belongs. We'll have to save it in miscellaneous files folder. BoxUtils.FileFolderInfo boxFolder = GetMiscellaneousFolder(); boxFile = BoxUtils.UploadFile(tokenHandler, boxFolder.ID, fileName, data).Result; } else { CheckForMissingNoteRecord(saveContext); var fileName = BoxUtils.CleanFileOrFolderName(Path.GetFileName(saveContext.FileInfo.Name)); string boxFolderID = GetOrCreateBoxFolderForNoteID(saveContext.NoteID.Value); try { boxFile = BoxUtils.UploadFile(tokenHandler, boxFolderID, fileName, data).Result; } catch (AggregateException ae) { ScreenUtils.HandleAggregateException(ae, HttpStatusCode.NotFound, exception => { using (new PXConnectionScope()) { BoxFolderCache folderCacheToDelete = FoldersByFolderID.Cache.CreateInstance() as BoxFolderCache; folderCacheToDelete.FolderID = boxFolderID; var deletedFolderInfo = FoldersByFolderID.Delete(folderCacheToDelete); Actions.PressSave(); } ScreenUtils.TraceAndThrowException(Messages.BoxFolderNotFoundRunSynchAgain, boxFolderID); }); } if (!string.IsNullOrEmpty(saveContext.FileInfo.Comment)) { BoxUtils.SetFileDescription(tokenHandler, boxFile.ID, saveContext.FileInfo.Comment).Wait(); } } var bfc = (BoxFileCache)FilesByBlobHandler.Cache.CreateInstance(); bfc.BlobHandler = blobHandlerGuid; bfc.FileID = boxFile.ID; bfc.ParentFolderID = boxFile.ParentFolderID; bfc = FilesByBlobHandler.Insert(bfc); Actions.PressSave(); return(blobHandlerGuid); }