/// <summary> /// Maps the specified folder. /// </summary> /// <param name="folder">The folder.</param> /// <param name="ministryFileType">Type of the ministry file.</param> /// <param name="storageProvider">The storage provider.</param> public void Map(ZipArchive folder, BinaryFileType ministryFileType, ProviderComponent storageProvider) { var lookupContext = new RockContext(); var personEntityTypeId = EntityTypeCache.GetId <Person>(); var fileFieldTypeId = FieldTypeCache.Read(Rock.SystemGuid.FieldType.FILE.AsGuid(), lookupContext).Id; var existingAttributes = new AttributeService(lookupContext).GetByFieldTypeId(fileFieldTypeId) .Where(a => a.EntityTypeId == personEntityTypeId) .ToDictionary(a => a.Key, a => a.Id); var emptyJsonObject = "{}"; var newFileList = new List <DocumentKeys>(); int completed = 0; int totalRows = folder.Entries.Count; int percentage = (totalRows - 1) / 100 + 1; ReportProgress(0, string.Format("Verifying files import ({0:N0} found.", totalRows)); foreach (var file in folder.Entries) { var fileExtension = Path.GetExtension(file.Name); var fileMimeType = Extensions.GetMIMEType(file.Name); if (BinaryFileComponent.FileTypeBlackList.Contains(fileExtension)) { LogException("Binary File Import", string.Format("{0} filetype not allowed ({1})", fileExtension, file.Name)); continue; } else if (fileMimeType == null) { LogException("Binary File Import", string.Format("{0} filetype not recognized ({1})", fileExtension, file.Name)); continue; } string[] parsedFileName = file.Name.Split('_'); // Ministry docs should follow this pattern: // 0. Firstname // 1. Lastname // 2. ForeignId // 3. Filename var personForeignId = parsedFileName[2].AsType <int?>(); var personKeys = BinaryFileComponent.ImportedPeople.FirstOrDefault(p => p.IndividualId == personForeignId); if (personKeys != null) { var rockFile = new Rock.Model.BinaryFile(); rockFile.IsSystem = false; rockFile.IsTemporary = false; rockFile.FileName = file.Name; rockFile.MimeType = fileMimeType; rockFile.BinaryFileTypeId = ministryFileType.Id; rockFile.CreatedDateTime = file.LastWriteTime.DateTime; rockFile.ModifiedDateTime = ImportDateTime; rockFile.Description = string.Format("Imported as {0}", file.Name); rockFile.SetStorageEntityTypeId(ministryFileType.StorageEntityTypeId); rockFile.StorageEntitySettings = emptyJsonObject; if (ministryFileType.AttributeValues.Any()) { rockFile.StorageEntitySettings = ministryFileType.AttributeValues .ToDictionary(a => a.Key, v => v.Value.Value).ToJson(); } // use base stream instead of file stream to keep the byte[] // NOTE: if byte[] converts to a string it will corrupt the stream using (var fileContent = new StreamReader(file.Open())) { rockFile.ContentStream = new MemoryStream(fileContent.BaseStream.ReadBytesToEnd()); } var attributePattern = "[A-Za-z0-9-]+"; var attributeName = Regex.Match(parsedFileName[3].RemoveWhitespace(), attributePattern); var attributeKey = attributeName.Value.RemoveWhitespace(); // change key to default key for Background Check Documents if (attributeKey == "BackgroundCheck") { attributeKey = "BackgroundCheckDocument"; } if (!existingAttributes.ContainsKey(attributeKey)) { var newAttribute = new Attribute(); newAttribute.FieldTypeId = fileFieldTypeId; newAttribute.EntityTypeId = personEntityTypeId; newAttribute.EntityTypeQualifierColumn = string.Empty; newAttribute.EntityTypeQualifierValue = string.Empty; newAttribute.Key = attributeKey; newAttribute.Name = attributeName.Value; newAttribute.Description = attributeName.Value + " created by binary file import"; newAttribute.CreatedDateTime = ImportDateTime; newAttribute.ModifiedDateTime = ImportDateTime; newAttribute.IsGridColumn = false; newAttribute.IsMultiValue = false; newAttribute.IsRequired = false; newAttribute.AllowSearch = false; newAttribute.IsSystem = false; newAttribute.Order = 0; newAttribute.AttributeQualifiers.Add(new AttributeQualifier() { Key = "binaryFileType", Value = ministryFileType.Guid.ToString() }); lookupContext.Attributes.Add(newAttribute); lookupContext.SaveChanges(); existingAttributes.Add(newAttribute.Key, newAttribute.Id); } newFileList.Add(new DocumentKeys() { PersonId = personKeys.PersonId, AttributeId = existingAttributes[attributeKey], File = rockFile }); completed++; if (completed % percentage < 1) { int percentComplete = completed / percentage; ReportProgress(percentComplete, string.Format("{0:N0} files imported ({1}% complete).", completed, percentComplete)); } else if (completed % ReportingNumber < 1) { SaveFiles(newFileList, storageProvider); // Reset list newFileList.Clear(); ReportPartialProgress(); } } } if (newFileList.Any()) { SaveFiles(newFileList, storageProvider); } ReportProgress(100, string.Format("Finished files import: {0:N0} addresses imported.", completed)); }
/// <summary> /// Maps the specified folder. /// </summary> /// <param name="folder">The folder.</param> /// <param name="ministryFileType">Type of the ministry file.</param> public int Map(ZipArchive folder, BinaryFileType ministryFileType) { var lookupContext = new RockContext(); var personEntityTypeId = EntityTypeCache.GetId <Person>(); var binaryFileTypeService = new BinaryFileTypeService(lookupContext); var fileFieldTypeId = FieldTypeCache.Get(Rock.SystemGuid.FieldType.FILE.AsGuid(), lookupContext).Id; var backgroundFieldTypeId = FieldTypeCache.Get(Rock.SystemGuid.FieldType.BACKGROUNDCHECK.AsGuid(), lookupContext).Id; var existingAttributes = new AttributeService(lookupContext).GetByFieldTypeId(fileFieldTypeId) .Where(a => a.EntityTypeId == personEntityTypeId) .ToDictionary(a => a.Key, a => a); var backgroundCheckFileAttributes = new AttributeService(lookupContext).GetByFieldTypeId(backgroundFieldTypeId) .Where(a => a.EntityTypeId == personEntityTypeId) .ToDictionary(a => a.Key, a => a); foreach (var backgroundCheckFileAttribute in backgroundCheckFileAttributes) { if (!existingAttributes.ContainsKey(backgroundCheckFileAttribute.Key)) { existingAttributes.Add(backgroundCheckFileAttribute.Key, backgroundCheckFileAttribute.Value); } } var emptyJsonObject = "{}"; var newFileList = new List <DocumentKeys>(); var completedItems = 0; var totalRows = folder.Entries.Count; var percentage = (totalRows - 1) / 100 + 1; ReportProgress(0, string.Format("Verifying ministry document import ({0:N0} found)", totalRows)); foreach (var file in folder.Entries.OrderBy(f => f.Name)) { var fileExtension = Path.GetExtension(file.Name); if (FileTypeBlackList.Contains(fileExtension)) { LogException("Binary File Import", string.Format("{0} filetype not allowed ({1})", fileExtension, file.Name)); continue; } var nameWithoutExtension = file.Name.ReplaceLastOccurrence(fileExtension, string.Empty); var parsedFileName = nameWithoutExtension.Split('_'); // Ministry docs should follow this pattern: // 0. Firstname // 1. Lastname // 2. ForeignId // 3. Filename // 4. Doc Id if (parsedFileName.Length < 3) { break; } var personForeignId = parsedFileName[2].AsType <int?>(); var personKeys = ImportedPeople.FirstOrDefault(p => p.PersonForeignId == personForeignId); if (personKeys != null) { var attributeName = string.Empty; var documentForeignId = string.Empty; if (parsedFileName.Count() > 4) { attributeName = parsedFileName[3]; documentForeignId = parsedFileName[4]; } else { var filename = parsedFileName[3].ReplaceLastOccurrence(fileExtension, string.Empty); attributeName = Regex.Replace(filename, "\\d{4,}[.\\w]+$", string.Empty); documentForeignId = Regex.Match(filename, "\\d+$").Value; } // append "Document" to attribute name to create unique attributes // this matches core attribute "Background Check Document" attributeName = !attributeName.EndsWith("Document", StringComparison.OrdinalIgnoreCase) ? string.Format("{0} Document", attributeName) : attributeName; var attributeKey = attributeName.RemoveSpecialCharacters(); Attribute fileAttribute = null; var attributeBinaryFileType = ministryFileType; if (!existingAttributes.ContainsKey(attributeKey)) { fileAttribute = new Attribute { FieldTypeId = fileFieldTypeId, EntityTypeId = personEntityTypeId, EntityTypeQualifierColumn = string.Empty, EntityTypeQualifierValue = string.Empty, Key = attributeKey, Name = attributeName, Description = string.Format("{0} created by binary file import", attributeName), IsGridColumn = false, IsMultiValue = false, IsRequired = false, AllowSearch = false, IsSystem = false, Order = 0 }; fileAttribute.AttributeQualifiers.Add(new AttributeQualifier() { Key = "binaryFileType", Value = ministryFileType.Guid.ToString() }); lookupContext.Attributes.Add(fileAttribute); lookupContext.SaveChanges(); existingAttributes.Add(fileAttribute.Key, fileAttribute); } else { // if attribute already exists in Rock, override default file type with the Rock-specified file type fileAttribute = existingAttributes[attributeKey]; var attributeBinaryFileTypeGuid = fileAttribute.AttributeQualifiers.FirstOrDefault(q => q.Key.Equals("binaryFileType")); if (attributeBinaryFileTypeGuid != null) { attributeBinaryFileType = binaryFileTypeService.Get(attributeBinaryFileTypeGuid.Value.AsGuid()); } } var rockFile = new Rock.Model.BinaryFile { IsSystem = false, IsTemporary = false, MimeType = GetMIMEType(file.Name), BinaryFileTypeId = attributeBinaryFileType.Id, FileName = file.Name, Description = string.Format("Imported as {0}", file.Name), CreatedDateTime = file.LastWriteTime.DateTime, ModifiedDateTime = file.LastWriteTime.DateTime, CreatedByPersonAliasId = ImportPersonAliasId, ForeignKey = documentForeignId, ForeignId = documentForeignId.AsIntegerOrNull() }; rockFile.SetStorageEntityTypeId(attributeBinaryFileType.StorageEntityTypeId); rockFile.StorageEntitySettings = emptyJsonObject; if (attributeBinaryFileType.AttributeValues != null) { rockFile.StorageEntitySettings = attributeBinaryFileType.AttributeValues .ToDictionary(a => a.Key, v => v.Value.Value).ToJson(); } // use base stream instead of file stream to keep the byte[] // NOTE: if byte[] converts to a string it will corrupt the stream using (var fileContent = new StreamReader(file.Open())) { rockFile.ContentStream = new MemoryStream(fileContent.BaseStream.ReadBytesToEnd()); } newFileList.Add(new DocumentKeys() { PersonId = personKeys.PersonId, AttributeId = fileAttribute.Id, File = rockFile }); completedItems++; if (completedItems % percentage < 1) { var percentComplete = completedItems / percentage; ReportProgress(percentComplete, string.Format("{0:N0} ministry document files imported ({1}% complete).", completedItems, percentComplete)); } if (completedItems % ReportingNumber < 1) { SaveFiles(newFileList); // Reset list newFileList.Clear(); ReportPartialProgress(); } } } if (newFileList.Any()) { SaveFiles(newFileList); } ReportProgress(100, string.Format("Finished documents import: {0:N0} ministry documents imported.", completedItems)); return(completedItems); }