/// <summary> /// Deletes the resource in inRiver, associated with the asset id of bynder /// </summary> /// <param name="bynderAssetId"></param> /// <returns></returns> public WorkerResult Execute(string bynderAssetId) { var result = new WorkerResult(); // only process if we are allowed to delete entities if (!GetDeleteResourceOnDeletedEvents()) { return(result); } // find resourceEntity based on bynderAssetId Entity resourceEntity = _inRiverContext.ExtensionManager.DataService.GetEntityByUniqueValue(FieldTypeIds.ResourceBynderId, bynderAssetId, LoadLevel.DataAndLinks); // delete if exist if (resourceEntity != null) { _inRiverContext.Log(LogLevel.Verbose, $"Deleting Resource {resourceEntity.Id}, which is associated with the deleted bynder asset {bynderAssetId}"); _inRiverContext.ExtensionManager.DataService.DeleteEntity(resourceEntity.Id); result.Messages.Add($"Deleted Resource {resourceEntity.Id}, which was associated with the deleted bynder asset {bynderAssetId}"); } else { _inRiverContext.Log(LogLevel.Debug, $"Nothing to remove. Deleted asset {bynderAssetId} does not exist in inRiver as Resource."); result.Messages.Add($"Nothing to remove. Deleted asset {bynderAssetId} does not exist in inRiver as Resource."); } return(result); }
public static string SaveAndZipDocument(string channelIdentifier, XDocument doc, string folderDateTime, Configuration config, inRiverContext context) { string dirPath = Path.Combine(config.PublicationsRootPath, folderDateTime); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } try { XDocument verified = VerifyAndCorrectDocument(doc, context); doc = verified; } catch (Exception exception) { context.Log(LogLevel.Error, "Fail to verify the document: ", exception); } string filePath = Path.Combine(dirPath, Configuration.ExportFileName); context.Log( LogLevel.Information, string.Format("Saving verified document to path {0} for channel:{1}", filePath, channelIdentifier)); doc.Save(filePath); string fullZippedFileName = string.Format( "inRiverExport_{0}_{1}.zip", channelIdentifier, DateTime.Now.ToString("yyyyMMdd-HHmmss")); ZipFile(filePath, fullZippedFileName); return(fullZippedFileName); }
public IEnumerable <string> UploadResourcesAndDocumentToAzure(List <StructureEntity> channelEntities, XDocument resourceDocument, Configuration config, string folderDateTime, inRiverContext context) { try { List <int> resourceIds = new List <int>(); foreach (StructureEntity structureEntity in channelEntities) { if (structureEntity.Type == "Resource" && !resourceIds.Contains(structureEntity.EntityId)) { resourceIds.Add(structureEntity.EntityId); } } context.Log(LogLevel.Debug, $"channel entities count {channelEntities.Count} in UploadResources to azure"); List <Entity> resources = context.ExtensionManager.DataService.GetEntities(resourceIds, LoadLevel.DataAndLinks); context.Log(LogLevel.Debug, $"resources count {resources.Count} after fetching them before passing them to UploadResourceFiles to azure"); return(UploadResourceFilesToAzureFileStorage(resources, resourceDocument, config, folderDateTime, context)); } catch (Exception ex) { context.Log(LogLevel.Error, "Could not add resources", ex); return(null); } }
public void Execute(Entity resourceEntity) { if (!resourceEntity.EntityType.Id.Equals(EntityTypeIds.Resource)) { return; } if (resourceEntity.LoadLevel < LoadLevel.DataOnly) { resourceEntity = _inRiverContext.ExtensionManager.DataService.GetEntity(resourceEntity.Id, LoadLevel.DataOnly); } string bynderDownloadState = (string)resourceEntity.GetField(FieldTypeIds.ResourceBynderDownloadState)?.Data; if (string.IsNullOrWhiteSpace(bynderDownloadState) || bynderDownloadState != BynderStates.Todo) { return; } string bynderId = (string)resourceEntity.GetField(FieldTypeIds.ResourceBynderId)?.Data; if (string.IsNullOrWhiteSpace(bynderId)) { return; } // download asset information Asset asset = _bynderClient.GetAssetByAssetId(bynderId); if (asset == null) { _inRiverContext.Log(LogLevel.Error, "Asset information is empty"); return; } // check for existing file var resourceFileId = resourceEntity.GetField(FieldTypeIds.ResourceFileId)?.Data; int existingFileId = resourceFileId != null ? (int)resourceFileId : 0; // add new asset string resourceFileName = (string)resourceEntity.GetField(FieldTypeIds.ResourceFilename)?.Data; int newFileId = _inRiverContext.ExtensionManager.UtilityService.AddFileFromUrl(resourceFileName, _bynderClient.GetAssetDownloadLocation(asset.Id).S3_File); // delete older asset file if (existingFileId > 0) { _inRiverContext.Log(LogLevel.Verbose, $"existing fileId found {existingFileId}"); _inRiverContext.ExtensionManager.UtilityService.DeleteFile(existingFileId); } // set fieltypes for resource entity resourceEntity.GetField(FieldTypeIds.ResourceFileId).Data = newFileId; resourceEntity.GetField(FieldTypeIds.ResourceMimeType).Data = asset.GetOriginalMimeType(); resourceEntity.GetField(FieldTypeIds.ResourceBynderDownloadState).Data = BynderStates.Done; _inRiverContext.ExtensionManager.DataService.UpdateEntity(resourceEntity); _inRiverContext.Logger.Log(LogLevel.Information, $"Updated resource entity {resourceEntity.Id}"); }
public XDocument GenerateXml(Entity entity, SchemabasedEntityActionEnum entityAction, Dictionary <string, string> uniqueFieldTypes, int channelId = 0, Link linkToBeDeleted = null) { XDocument doc = null; if (entity == null) { context.Log(LogLevel.Error, "Entity argument is null in Generate Xml in SchemabasedOutput. Aborting."); return(doc); } try { this.currentChannelId = channelId; this.deletedLink = linkToBeDeleted; ReGenerateSchema(entity.EntityType.Id, false); doc = this.GetDocumentBase(entity.EntityType.Id); XElement root = doc.Element(targetNamespace + entity.EntityType.Id + "s"); if (root != null) { string uniqueFieldType = string.Empty; if (uniqueFieldTypes.ContainsKey(entity.EntityType.Id)) { uniqueFieldType = uniqueFieldTypes[entity.EntityType.Id]; } root.Add(this.CreateEntity(entity, entityAction, uniqueFieldType, uniqueFieldTypes)); } } catch (Exception exception) { context.Log(LogLevel.Error, $"Error during generating xml for entity id {entity.Id}:", exception); doc = null; } return(doc); }
internal string ZipAndUploadToCloud(Configuration config, inRiverContext context, Dictionary <string, byte[]> files, CloudFileDirectory cloudDirectory, CloudFile cloudFile) { using (MemoryStream stream = new MemoryStream()) { using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create, true)) { foreach (KeyValuePair <string, byte[]> imageFile in files) { ZipArchiveEntry entry = archive.CreateEntry(imageFile.Key); using (Stream entryStream = entry.Open()) { entryStream.Write(imageFile.Value, 0, imageFile.Value.Length); } } } stream.Position = 0; cloudFile.UploadFromStream(stream); Uri path = cloudFile.Uri; config.ResourceNameInCloud = cloudFile.Name; context.Log(LogLevel.Debug, $"done uploading resource files to the file storage in {cloudDirectory} and this is it's uri {path}"); return(path.ToString()); } }
public static void ZipDirectoryAndSubdirectory(string zippedFileName, Configuration configuration, inRiverContext context) { context.Log(LogLevel.Debug, "Zipping resource directory"); Stopwatch dirZipStopWatch = new Stopwatch(); try { dirZipStopWatch.Start(); string directoryToZip = Path.Combine(configuration.ResourcesRootPath, "temp"); DirectoryInfo directoryInfo = new DirectoryInfo(directoryToZip); string fullZippedFileName = Path.Combine(configuration.ResourcesRootPath, zippedFileName); using (Package zip = Package.Open(fullZippedFileName, FileMode.Create)) { foreach (DirectoryInfo di in directoryInfo.GetDirectories()) { foreach (FileInfo fi in di.GetFiles()) { string destFilename = string.Format(".\\{0}\\{1}", di.Name, fi.Name); ZipFile(zip, fi, destFilename); } } foreach (FileInfo fi in directoryInfo.GetFiles()) { if (fi.Name.Equals(zippedFileName)) { continue; } string destFilename = string.Format(".\\{0}", fi.Name); ZipFile(zip, fi, destFilename); } } dirZipStopWatch.Stop(); } catch (Exception ex) { context.Log(LogLevel.Error, "Exception in ZipDirectoryAndSubdirectoryAndRemoveFiles", ex); } BusinessHelper businessHelper = new BusinessHelper(context); context.Log( LogLevel.Information, string.Format("Resource directory zipped, took {0}!", businessHelper.GetElapsedTimeFormated(dirZipStopWatch))); }
internal XDocument GetChannelStructure(int channelId) { try { string channelStructure = _context.ExtensionManager.ChannelService.GetChannelStructure(channelId); if (!string.IsNullOrEmpty(channelStructure)) { return(XDocument.Parse(channelStructure)); } } catch (Exception ex) { _context.Log(LogLevel.Error, "Error in GetChannelStructure", ex); } return(new XDocument()); }
/// <summary> /// Creates the resource document by looping through the channel entities /// </summary> /// <param name="channelEntities">A <see cref="List{StructureEntity}"/> object</param> /// <param name="config">The Episerver <see cref="Configuration" /> object</param> /// <returns>Episerver Xml document as a <see cref="XDocument"/></returns> public XDocument GetResourcesDocument(List <StructureEntity> channelEntities, Configuration config) { XDocument resourceDocument = new XDocument(); try { List <int> resourceIds = new List <int>(); foreach (StructureEntity structureEntity in channelEntities) { if (structureEntity.Type == "Resource" && !resourceIds.Contains(structureEntity.EntityId)) { resourceIds.Add(structureEntity.EntityId); } } List <Entity> resources = _context.ExtensionManager.DataService.GetEntities(resourceIds, LoadLevel.DataAndLinks); EntityType reourceType = resources.Count > 0 ? resources[0].EntityType : _context.ExtensionManager.ModelService.GetEntityType("Resource"); XElement resourceMetaClasses = _epiElement.CreateResourceMetaFieldsElement(reourceType, config); resourceDocument = CreateResourceDocument(resourceMetaClasses, resources, resources, "added", config); } catch (Exception ex) { _context.Log(LogLevel.Error, string.Format("Could not add resources"), ex); } return(resourceDocument); }
public CultureInfo GetChannelDefaultLanguage(Configuration configuration, Entity channel) { Field defaultLanguageField = channel.Fields.FirstOrDefault(f => f.FieldType.Id.ToLower().Contains("channeldefaultlanguage")); if (defaultLanguageField == null || defaultLanguageField.IsEmpty()) { if (configuration.LanguageMapping?.Any() ?? false) { _context.Log(LogLevel.Debug, $"Using '{configuration.LanguageMapping.Values.First()}' as default language."); return(configuration.LanguageMapping.Values.First()); } _context.Log(LogLevel.Debug, $"Using 'en-US' as default language."); return(new CultureInfo("en-us")); } _context.Log(LogLevel.Debug, $"Using '{defaultLanguageField.Data}' as default language."); return(new CultureInfo(defaultLanguageField.Data.ToString())); }
private CVLDataMode StringToCVLDataMode(string str) { CVLDataMode mode; if (!Enum.TryParse(str, out mode)) { _context.Log(LogLevel.Error, string.Format("Could not parse CVLDataMode for string {0}", str)); } return(mode); }
internal ConnectorEvent InitiateConnectorEvent(ConnectorEventType messageType, string message, int percentage, bool error = false) { string channelId; _context.Settings.TryGetValue("CHANNEL_ID", out channelId); ConnectorEvent connectorEvent = new ConnectorEvent { ChannelId = int.Parse(channelId ?? "0"), ConnectorEventType = messageType, ConnectorId = _context.ExtensionId, EventTime = DateTime.Now, SessionId = Guid.NewGuid(), Percentage = percentage, IsError = error, Message = message }; _context.Log(LogLevel.Information, connectorEvent.Message); return(connectorEvent); }
public Configuration(inRiverContext context) { _context = context; settings = context.Settings; LinkTypes = new List <LinkType>(context.ExtensionManager.ModelService.GetAllLinkTypes()); epiFieldsIninRiver = new List <string> { "startdate", "enddate", "displaytemplate", "seodescription", "seokeywords", "seotitle", "seouri", "skus" }; ChannelStructureEntities = new List <StructureEntity>(); ChannelEntities = new Dictionary <int, Entity>(); context.Log(LogLevel.Debug, $"A new instance of {GetType().FullName} was created."); }
public string FieldIsUseInCompare(FieldType fieldType) { string value = "False"; if (fieldType.Settings.ContainsKey("UseInComparing")) { value = fieldType.Settings["UseInComparing"]; if (!(value.ToLower().Equals("false") || value.ToLower().Equals("true"))) { _context.Log(LogLevel.Error, string.Format("Fieldtype with id {0} has invalid UseInComparing setting", fieldType.Id)); } } return(value); }
public static void SaveDocument(string channelIdentifier, XDocument doc, Configuration config, string folderDateTime, inRiverContext context) { string dirPath = Path.Combine(config.ResourcesRootPath, folderDateTime); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } string filePath = Path.Combine(dirPath, "Resources.xml"); context.Log( LogLevel.Information, string.Format("Saving document to path {0} for channel:{1}", filePath, channelIdentifier)); doc.Save(filePath); }
private static XDocument VerifyAndCorrectDocument(XDocument doc, inRiverContext context) { List <string> unwantedEntityTypes = CreateUnwantedEntityTypeList(context); XDocument result = new XDocument(doc); XElement root = result.Root; if (root == null) { throw new Exception("Can't verify the Catalog.cml as it's empty."); } IEnumerable <XElement> entryElements = root.Descendants("Entry"); List <string> codesToBeRemoved = new List <string>(); foreach (XElement entryElement in entryElements) { string code = entryElement.Elements("Code").First().Value; string metaClassName = entryElement.Elements("MetaData").Elements("MetaClass").Elements("Name").First().Value; if (unwantedEntityTypes.Contains(metaClassName)) { context.Log( LogLevel.Debug, string.Format("Code {0} will be removed as it has wrong metaclass name ({1})", code, metaClassName)); codesToBeRemoved.Add(code); } } foreach (string code in codesToBeRemoved) { string theCode = code; root.Descendants("Entry").Where( e => { XElement codeElement = e.Element("Code"); return(codeElement != null && codeElement.Value == theCode); }).Remove(); } return(result); }
internal XDocument CreateResourceDocument(XElement resourceMetaClasses, List <Entity> channelResources, List <Entity> resources, string action, Configuration config) { Dictionary <int, Entity> parentEntities = config.ChannelEntities; int imageCount = resources.Count(resource => { string mainCategoryKey = resource.GetField("ResourceMainCategory")?.Data as string; return(mainCategoryKey == "Image"); }); _context?.Log(LogLevel.Debug, string.Format("Episerver imageCount {0}", imageCount.ToString())); return (new XDocument( new XElement( "Resources", resourceMetaClasses, new XElement( "ResourceFiles", resources.Select(res => _epiElement.CreateResourceElement(res, action, config, parentEntities, imageCount)))))); }
public void ImportEntities(IEnumerable <MappedEntity> mappedEntities) { int count = 0; foreach (MappedEntity mappedEntity in mappedEntities) { bool newEntity = false; Entity entity = _entityRepository .GetEntityByUniqueValue( mappedEntity.UniqueFieldType, mappedEntity.UniqueFieldValue, LoadLevel.DataOnly); if (entity == null) { EntityType entityType = _modelsRepository .GetEntityType(mappedEntity.EntityType); entity = Entity.CreateEntity(entityType); newEntity = true; } bool entityModified = false; foreach (MappedField mappedField in mappedEntity.Fields) { // This extension method is much more efficient than the built-in GetField() method. Field field = entity.GetFieldOrdinal(mappedField.Name); if (field == null) { throw new InvalidOperationException( $"The field '{mappedField.Name}' does not exist in the model."); } object fieldValue = mappedField.Value; field.Data = fieldValue; entityModified = true; } if (entity.FieldSetId != mappedEntity.FieldSet) { entity.FieldSetId = mappedEntity.FieldSet; entityModified = true; } if (entity.Id == 0) { entity = _entityRepository.AddEntity(entity); } else if (entityModified) { entity = _entityRepository.UpdateEntity(entity); } foreach (MappedLink mappedLink in mappedEntity.Links) { ImportLink(mappedLink, entity, newEntity); } count++; } _context.Log(LogLevel.Information, $"Finished importing {count} entities."); }
internal void Add(Entity channelEntity, ConnectorEvent connectorEvent, out bool resourceIncluded) { resourceIncluded = false; var channelHelper = new ChannelHelper(_context); var epiApi = new EpiApi(_context); var connectorEventHelper = new ConnectorEventHelper(_context); connectorEventHelper.UpdateConnectorEvent(connectorEvent, "Generating catalog.xml...", 11); Dictionary <string, List <XElement> > epiElements = _epiDocument.GetEPiElements(ConnectorConfig); XDocument doc = _epiDocument.CreateImportDocument( channelEntity, null, null, epiElements, ConnectorConfig); string folderDateTime = DateTime.Now.ToString("yyyyMMdd-HHmmss.fff"); if (!DocumentFileHelper.ZipDocumentAndUploadToAzure(XmlDocumentType.Catalog, doc, ConnectorConfig, folderDateTime)) { _context.Log(LogLevel.Information, "Failed to zip and upload the catalog file to azure from add utility Add() method"); } _context.Log(LogLevel.Information, "Catalog saved with the following:"); _context.Log(LogLevel.Information, string.Format("Nodes: {0}", epiElements["Nodes"].Count)); _context.Log(LogLevel.Information, string.Format("Entries: {0}", epiElements["Entries"].Count)); _context.Log(LogLevel.Information, string.Format("Relations: {0}", epiElements["Relations"].Count)); _context.Log(LogLevel.Information, string.Format("Associations: {0}", epiElements["Associations"].Count)); connectorEventHelper.UpdateConnectorEvent(connectorEvent, "Done generating catalog.xml", 25); connectorEventHelper.UpdateConnectorEvent(connectorEvent, "Generating Resource.xml and saving files to disk...", 26); Resources resourceHelper = new Resources(_context); XDocument resourceDocument = resourceHelper.GetResourcesDocument(ConnectorConfig.ChannelStructureEntities, ConnectorConfig); // Add all files included in resource document Dictionary <string, byte[]> files = new Dictionary <string, byte[]>(); IEnumerable <XElement> resourceFileElements = resourceDocument.Document.Element("Resources")?.Element("ResourceFiles")?.Elements("Resource"); if (resourceFileElements != null && resourceFileElements.Any()) { _context.Log(LogLevel.Information, $"Adding {resourceFileElements.Count()} resource files to zip archive."); foreach (XElement resourceFileElement in resourceFileElements) { int resourceEntityId; if (int.TryParse(resourceFileElement.Attribute("id").Value, out resourceEntityId)) { Entity targetEntity = _context.ExtensionManager.DataService.GetEntity(resourceEntityId, LoadLevel.DataOnly); _context.Log(LogLevel.Debug, $"Adding image file {targetEntity.DisplayName}({targetEntity.Id})"); int resourceFileId = resourceHelper.GetResourceFileId(targetEntity); foreach (string displayConfig in resourceHelper.GetDisplayConfigurations(targetEntity, ConnectorConfig)) { string fileName = resourceHelper.GetResourceFileName(targetEntity, resourceFileId, displayConfig, ConnectorConfig); byte[] resourceData = _context.ExtensionManager.UtilityService.GetFile(resourceFileId, displayConfig); if (resourceData != null) { files.Add($"{displayConfig}/{fileName}", resourceData); } } } } } else { string elementCount = resourceFileElements == null ? "null" : resourceFileElements.Count().ToString(); _context.Log(LogLevel.Information, $"No files linked to resource document. Document contains {elementCount} elements"); } DocumentFileHelper.ZipDocumentAndUploadToAzure(XmlDocumentType.Resources, resourceDocument, ConnectorConfig, folderDateTime, files); connectorEventHelper.UpdateConnectorEvent(connectorEvent, "Done generating/saving Resource.xml", 50); if (ConnectorConfig.ActivePublicationMode.Equals(PublicationMode.Automatic)) { _context.Log(LogLevel.Debug, "Starting automatic import!"); connectorEventHelper.UpdateConnectorEvent(connectorEvent, "Sending Catalog.xml to EPiServer...", 51); if (epiApi.StartImportIntoEpiServerCommerce(ConnectorConfig.CatalogPathInCloud, channelHelper.GetChannelGuid(channelEntity, ConnectorConfig), ConnectorConfig)) { connectorEventHelper.UpdateConnectorEvent(connectorEvent, "Done sending Catalog.xml to EPiServer", 75); } else { connectorEventHelper.UpdateConnectorEvent(connectorEvent, "Error while sending Catalog.xml to EPiServer", -1, true); return; } connectorEventHelper.UpdateConnectorEvent(connectorEvent, "Sending Resources to EPiServer...", 76); if (epiApi.StartAssetImportIntoEpiServerCommerce(ConnectorConfig.ResourceNameInCloud, Path.Combine(ConnectorConfig.ResourcesRootPath, folderDateTime), ConnectorConfig)) { connectorEventHelper.UpdateConnectorEvent(connectorEvent, "Done sending Resources to EPiServer...", 99); resourceIncluded = true; } else { connectorEventHelper.UpdateConnectorEvent(connectorEvent, "Error while sending resources to EPiServer", -1, true); } } }
public void Delete(Entity channelEntity, int parentEntityId, Entity targetEntity, string linkTypeId, List <int> productParentIds = null) { var channelHelper = new ChannelHelper(_context); string channelIdentifier = channelHelper.GetChannelIdentifier(channelEntity); string folderDateTime = DateTime.Now.ToString("yyyyMMdd-HHmmss.fff"); channelHelper.BuildEntityIdAndTypeDict(DeleteUtilConfig); if (!DeleteUtilConfig.ChannelEntities.ContainsKey(targetEntity.Id)) { DeleteUtilConfig.ChannelEntities.Add(targetEntity.Id, targetEntity); } string resourceZipFile = string.Format("resource_{0}.zip", folderDateTime); if (_context.ExtensionManager.ChannelService.EntityExistsInChannel(channelEntity.Id, targetEntity.Id)) { var existingEntities = _context.ExtensionManager.ChannelService.GetAllStructureEntitiesForEntityInChannel( channelEntity.Id, targetEntity.Id); Entity parentEnt = _context.ExtensionManager.DataService.GetEntity(parentEntityId, LoadLevel.DataOnly); if (parentEnt != null) { if (!DeleteUtilConfig.ChannelEntities.ContainsKey(parentEnt.Id)) { DeleteUtilConfig.ChannelEntities.Add(parentEnt.Id, parentEnt); } if (targetEntity.EntityType.Id == "Resource") { DeleteResource( targetEntity, parentEnt, channelIdentifier, folderDateTime, resourceZipFile); } else { DeleteEntityThatStillExistInChannel( channelEntity, targetEntity, parentEnt, linkTypeId, existingEntities, channelIdentifier, folderDateTime, resourceZipFile); } } else { _context.Log(LogLevel.Information, $"Unable to find entity {parentEntityId} (already deleted?)"); } } else { //DeleteEntity DeleteEntity( channelEntity, parentEntityId, targetEntity, linkTypeId, channelIdentifier, folderDateTime, productParentIds); } }
public void DeleteCatalog(int catalogId, Configuration config) { lock (SingletonEPiLock.Instance) { try { RestEndpoint <int> endpoint = new RestEndpoint <int>(config.Settings, "DeleteCatalog", this._context); endpoint.Post(catalogId); } catch (Exception exception) { _context.Log(LogLevel.Error, $"Failed to delete catalog with id: {catalogId}", exception); } } }
public void AddCvl(string cvlId, string folderDateTime) { List <XElement> metafields = new List <XElement>(); List <FieldType> affectedFieldTypes = _businessHelper.GetFieldTypesWithCVL(cvlId, CvlUtilConfig); foreach (FieldType fieldType in affectedFieldTypes) { if (_epiMappingHelper.SkipField(fieldType, CvlUtilConfig)) { continue; } XElement metaField = _epiElement.InRiverFieldTypeToMetaField(fieldType, CvlUtilConfig); if (fieldType.DataType.Equals(DataType.CVL)) { metaField.Add(_epiMappingHelper.GetDictionaryValues(fieldType, CvlUtilConfig)); } if (metafields.Any( mf => { XElement nameElement = mf.Element("Name"); return(nameElement != null && nameElement.Value.Equals(_epiMappingHelper.GetEPiMetaFieldNameFromField(fieldType, CvlUtilConfig))); })) { XElement existingMetaField = metafields.FirstOrDefault( mf => { XElement nameElement = mf.Element("Name"); return(nameElement != null && nameElement.Value.Equals(_epiMappingHelper.GetEPiMetaFieldNameFromField(fieldType, CvlUtilConfig))); }); if (existingMetaField == null) { continue; } var movefields = metaField.Elements("OwnerMetaClass"); existingMetaField.Add(movefields); } else { metafields.Add(metaField); } } XElement metaData = new XElement("MetaDataPlusBackup", new XAttribute("version", "1.0"), metafields.ToArray()); XDocument doc = _epiDocument.CreateDocument(null, metaData, null, CvlUtilConfig); Entity channelEntity = _context.ExtensionManager.DataService.GetEntity(CvlUtilConfig.ChannelId, LoadLevel.DataOnly); if (channelEntity == null) { _context.Log(LogLevel.Error, string.Format("Could not find channel {0} for cvl add", CvlUtilConfig.ChannelId)); return; } string channelIdentifier = _channelHelper.GetChannelIdentifier(channelEntity); if (!DocumentFileHelper.ZipDocumentAndUploadToAzure(XmlDocumentType.Catalog, doc, CvlUtilConfig, folderDateTime)) { _context.Log(LogLevel.Information, "Failed to zip and upload the catalog file to azure from cvl utility AddCvl() method"); } _context.Log(LogLevel.Debug, string.Format("catalog {0} saved", channelIdentifier)); if (CvlUtilConfig.ActivePublicationMode.Equals(PublicationMode.Automatic)) { _context.Log(LogLevel.Debug, "Starting automatic import!"); _epiApi.StartImportIntoEpiServerCommerce( Path.Combine(CvlUtilConfig.PublicationsRootPath, folderDateTime, Configuration.ExportFileName), _channelHelper.GetChannelGuid(channelEntity, CvlUtilConfig), CvlUtilConfig); } }
/// <summary> /// Main method of the worker /// </summary> /// <param name="bynderAssetId"></param> /// <param name="notificationType"></param> /// <returns></returns> public WorkerResult Execute(string bynderAssetId, NotificationType notificationType) { var result = new WorkerResult(); // get original filename, as we need to evaluate this for further processing var asset = _bynderClient.GetAssetByAssetId(bynderAssetId); // evaluate filename string originalFileName = asset.GetOriginalFileName(); var evaluatorResult = _fileNameEvaluator.Evaluate(originalFileName); if (!evaluatorResult.IsMatch()) { result.Messages.Add($"Not processing '{originalFileName}'; does not match regex."); return(result); } // evaluate conditions if (!AssetAppliesToConditions(asset)) { _inRiverContext.Log(LogLevel.Debug, $"Asset {bynderAssetId} does not apply to the conditions"); result.Messages.Add($"Not processing '{originalFileName}'; does not apply to import conditions."); return(result); } _inRiverContext.Log(LogLevel.Debug, $"Asset {asset.Id} applies to conditions."); // find resourceEntity based on bynderAssetId Entity resourceEntity = _inRiverContext.ExtensionManager.DataService.GetEntityByUniqueValue(FieldTypeIds.ResourceBynderId, bynderAssetId, LoadLevel.DataAndLinks); // handle notification logic switch (notificationType) { case NotificationType.DataUpsert: return(CreateOrUpdateEntityAndRelations(result, asset, evaluatorResult, resourceEntity)); case NotificationType.MetadataUpdated: if (resourceEntity != null) { return(UpdateMetadata(result, asset, resourceEntity)); } else { return(CreateOrUpdateEntityAndRelations(result, asset, evaluatorResult, resourceEntity)); } case NotificationType.IsArchived: if (resourceEntity != null) { return(SetValuesOnResource(result, bynderAssetId, resourceEntity)); } else { _inRiverContext.Log(LogLevel.Debug, $"Archived asset {bynderAssetId}, does not exist in inRiver as Resource."); result.Messages.Add($"Archived asset {bynderAssetId}, does not exist in inRiver as Resource."); return(result); } default: _inRiverContext.Log(LogLevel.Warning, $"Notification type {notificationType} is not implemented yet! This notification will not be processed for asset {bynderAssetId}."); result.Messages.Add($"Notification type {notificationType} is not implemented yet! This notification will not be processed for asset {bynderAssetId}."); return(result); } }
public bool ImportResources(string fileNameInCloud, string baseResourcePath, string id) { context.Log(LogLevel.Information, string.Format("Starting Resource Import. Manifest: {0} BaseResourcePath: {1}", fileNameInCloud, baseResourcePath)); // Get custom setting this.settings = context.Settings; // Check if ENABLE_EPI_ENDPOINT is set, and set to false bool enableEndPoint = true; if (this.settings.ContainsKey("ENABLE_EPI_ENDPOINT")) { string valueEnableEPIEndpoint = settings["ENABLE_EPI_ENDPOINT"]; if (!string.IsNullOrEmpty(valueEnableEPIEndpoint)) { enableEndPoint = bool.Parse(valueEnableEPIEndpoint); } } if (!enableEndPoint) { context.Log(LogLevel.Information, "EPI Endpoint Disabled under Configuration"); return(true); } string apikey; if (this.settings.ContainsKey("EPI_APIKEY")) { apikey = this.settings["EPI_APIKEY"]; } else { throw new ConfigurationErrorsException("Missing EPI_APIKEY setting on connector. It needs to be defined to else the calls will fail. Please see the documentation."); } int timeout; if (this.settings.ContainsKey("EPI_RESTTIMEOUT")) { string timeoutString = this.settings["EPI_RESTTIMEOUT"]; if (!int.TryParse(timeoutString, out timeout)) { throw new ConfigurationErrorsException("Can't parse EPI_RESTTIMEOUT : " + timeoutString); } } else { throw new ConfigurationErrorsException("Missing EPI_RESTTIMEOUT setting on connector. It needs to be defined to else the calls will fail. Please see the documentation."); } if (this.settings.ContainsKey("EPI_ENDPOINT_URL") == false) { throw new ConfigurationErrorsException("Missing EPI_ENDPOINT_URL setting on connector. It should point to the import end point on the EPiServer Commerce web site. Please see the documentation."); } string endpointAddress = this.settings["EPI_ENDPOINT_URL"]; if (string.IsNullOrEmpty(endpointAddress)) { throw new ConfigurationErrorsException("Missing EPI_ENDPOINT_URL setting on connector. It should point to the import end point on the EPiServer Commerce web site. Please see the documentation."); } if (endpointAddress.EndsWith("/") == false) { endpointAddress = endpointAddress + "/"; } // Name of resource import controller method endpointAddress = endpointAddress + "ImportResources"; return(this.ImportResourcesToEPiServerCommerce(fileNameInCloud, baseResourcePath, endpointAddress, apikey, timeout)); }
internal IEnumerable <string> UploadResourceFilesToAzureFileStorage(List <Entity> resources, XDocument importXml, Configuration config, string folderDateTime, inRiverContext context) { Stopwatch saveFileStopWatch = new Stopwatch(); List <string> cloudFileNames = new List <string>(); try { // validate configuration settings if (string.IsNullOrEmpty(config.StorageAccountName) || string.IsNullOrEmpty(config.StorageAccountKey) || string.IsNullOrEmpty(config.StorageAccountShareReference) || string.IsNullOrEmpty(config.StorageAccountCatalogDirectoryReference) || string.IsNullOrEmpty(config.StorageAccountResourcesDirectoryReference)) { context.Log(LogLevel.Warning, $"Azure config settings are invalid: " + $"StorageAccountName: {config.StorageAccountName}, " + $"StorageAccountKey: {config.StorageAccountKey}, " + $"StorageAccountShareReference: {config.StorageAccountShareReference}, " + $"StorageAccountCatalogDirectoryReference: {config.StorageAccountCatalogDirectoryReference}, " + $"StorageAccountResourcesDirectoryReference: {config.StorageAccountResourcesDirectoryReference}"); return(cloudFileNames); } // validate resources argument if (resources == null) { context.Log(LogLevel.Error, "Resource is null!"); return(cloudFileNames); } // create varible files to hold filename and binary Dictionary <string, byte[]> files = new Dictionary <string, byte[]>(); // setup credentials and storage account StorageCredentials credentials = new StorageCredentials(config.StorageAccountName, config.StorageAccountKey); CloudStorageAccount storageAccount = new CloudStorageAccount(credentials, true); // setup file client and remoge share CloudFileClient fileClient = storageAccount.CreateCloudFileClient(); CloudFileShare share = fileClient.GetShareReference(config.StorageAccountShareReference); share.CreateIfNotExists(); // setup root directory and resource directory CloudFileDirectory root = share.GetRootDirectoryReference(); CloudFileDirectory directory = root.GetDirectoryReference(config.GetAzureStorageDirectoryName(XmlDocumentType.Resources)); directory.CreateIfNotExists(); saveFileStopWatch.Start(); // setup resource helper object Resources resourcesObj = new Resources(context); // setup the uncompressed file size total counter int totalFileSize = 0; // setup the azure file counter int fileCount = 0; // setup the file id list List <int> fileIdList = new List <int>(); foreach (Entity resource in resources) { // get the file id of the resource int resourceFileId = resourcesObj.GetResourceFileId(resource); // ensure the resource id has a proper id if (resourceFileId < 0) { context.Log(LogLevel.Information, $"Resource with id:{resource.Id} has no value for ResourceFileId"); continue; } // loop through each display configurations foreach (string displayConfiguration in resourcesObj.GetDisplayConfigurations(resource, config)) { // setup the fileName to use the output file extension from display configuration string fileName = resourcesObj.GetResourceFileName(resource, resourceFileId, displayConfiguration, config); // if the file for some reason already exists, continue to the next display configuration if (files.ContainsKey(fileName)) { context.Log(LogLevel.Debug, $"{fileName} already exists in the files collection and is skipped"); continue; } // get file bytes byte[] resourceData = context.ExtensionManager.UtilityService.GetFile(resourceFileId, displayConfiguration); // make sure we recieved the file from the utility service if (resourceData == null) { context.Log(LogLevel.Error, $"Resource with id:{resource.Id} and ResourceFileId: {resourceFileId} could not get file"); continue; } // add the current resource file id to the list fileIdList.Add(resource.Id); // log the resource file name context.Log(LogLevel.Debug, $"Adding resource {displayConfiguration}/{fileName}"); // add the file to the files collection files.Add($"{displayConfiguration}/{fileName}", resourceData); // add size to total file size counter totalFileSize += resourceData.Length; } if (totalFileSize > (config.TotalResourceSizeLimitMb * 1024 * 1024)) { try { // increase file counter fileCount++; // setup remote zip file CloudFile cloudFile = directory.GetFileReference(GetZipFileName(config, XmlDocumentType.Resources, folderDateTime, fileCount)); // setup reader using (XmlReader reader = importXml.CreateReader()) { // create a new file that only contains the elements specified in the file id list XmlDocument doc = XmlSplitUtility.GetPartialResourcesXml(reader, fileIdList); // log the resource file name context.Log(LogLevel.Debug, "Adding Resources.xml"); // setup memory a stream using (MemoryStream stream = new MemoryStream()) { // create a xml writer to format output using (XmlWriter writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true })) { // save partial document to the xml writer doc.Save(writer); // add the partial document to the files collection files.Add("Resources.xml", stream.ToArray()); } } // send the zipped file to Azure and store the file name cloudFileNames.Add(ZipAndUploadToCloud(config, context, files, directory, cloudFile)); // clear the id list fileIdList.Clear(); // clear the file list files.Clear(); // reset total file size totalFileSize = 0; } } catch (Exception ex) { context.Log(LogLevel.Error, "An error occured while sending the resources to the cloud.", ex); } } } // make sure to send the final files if (files.Any()) { try { // increase file counter fileCount++; // setup remote zip file CloudFile cloudFile = directory.GetFileReference(GetZipFileName(config, XmlDocumentType.Resources, folderDateTime, fileCount)); // setup reader using (XmlReader reader = importXml.CreateReader()) { // create a new file that only contains the elements specified in the file id list XmlDocument doc = XmlSplitUtility.GetPartialResourcesXml(reader, fileIdList); // log the resource file name context.Log(LogLevel.Debug, "Adding Resources.xml"); // setup memory a stream using (MemoryStream stream = new MemoryStream()) { // create a xml writer to format output using (XmlWriter writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true })) { // save partial document to the xml writer doc.Save(writer); // add the partial document to the files collection files.Add("Resources.xml", stream.ToArray()); } } // send the zipped file to Azure and store the file name cloudFileNames.Add(ZipAndUploadToCloud(config, context, files, directory, cloudFile)); } } catch (Exception ex) { context.Log(LogLevel.Error, "An error occured while sending the resources to the cloud.", ex); } } } catch (Exception ex) { context.Log(LogLevel.Error, "An error occured while sending the resources to the cloud.", ex); } return(cloudFileNames); }
public string Post(T message) { if (!enableEndPoint) { _context.Log(LogLevel.Information, "EPI Endpoint Disabled under Configuration"); return(string.Empty); } Uri uri = new Uri(this.GetUrl()); HttpClient client = new HttpClient(); string baseUrl = uri.Scheme + "://" + uri.Authority; _context.Log(LogLevel.Information, $"Posting to {uri}"); client.BaseAddress = new Uri(baseUrl); // Add an Accept header for JSON format. client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Add("apikey", this.apikey); // HttpResponseMessage response = client.GetAsync("").Result; // Blocking call! client.Timeout = new TimeSpan(this.timeout, 0, 0); HttpResponseMessage response = client.PostAsJsonAsync(uri.PathAndQuery, message).Result; if (response.IsSuccessStatusCode) { // Parse the response body. Blocking! string resp = response.Content.ReadAsAsync <string>().Result; _context.Log(LogLevel.Debug, $"Post response - Message:{message} Result:{resp} URI:{uri.PathAndQuery}"); int tries = 0; RestEndpoint <string> endpoint = new RestEndpoint <string>(this.settingsDictionary, "IsImporting", this._context); while (resp == "importing") { tries++; if (tries < 10) { Thread.Sleep(2000); } else if (tries < 30) { Thread.Sleep(30000); } else { Thread.Sleep(300000); } resp = endpoint.Get(); if (tries == 1 || (tries % 5 == 0)) { _context.Log(LogLevel.Debug, $"Post - GET - Message:{message} Retries:{tries} Response:{resp} URI:{uri.PathAndQuery}"); } } if (resp.StartsWith("ERROR")) { _context.Log(LogLevel.Error, resp); } return(resp); } string errorMsg = string.Format("Import failed: {0} ({1})", (int)response.StatusCode, response.ReasonPhrase); _context.Log(LogLevel.Error, errorMsg); throw new HttpRequestException(errorMsg); }
/// <summary> /// Fills skeleton with child elements (entity, nodes and relations) /// </summary> /// <param name="epiElements"></param> /// <param name="config"></param> private void FillElementList(Dictionary <string, List <XElement> > epiElements, Configuration config) { try { if (!epiElements["Nodes"].Any(e => { XElement element = e.Element("Code"); return(element != null && element.Value.Equals(config.ChannelIdPrefix + "_inRiverAssociations")); })) { epiElements["Nodes"].Add(_epiElement.CreateAssociationNodeElement("inRiverAssociations", config)); _context.Log(LogLevel.Debug, string.Format("Added channelNode {0} to Nodes", "inRiverAssociations")); } List <string> addedEntities = new List <string>(); List <string> addedNodes = new List <string>(); List <string> addedRelations = new List <string>(); int totalLoaded = 0; int batchSize = config.BatchSize; do { var batch = config.ChannelStructureEntities.Skip(totalLoaded).Take(batchSize).ToList(); config.ChannelEntities = GetEntitiesInStructure(batch); FillElements(batch, config, addedEntities, addedNodes, addedRelations, epiElements); totalLoaded += batch.Count; _context.Log(LogLevel.Debug, string.Format("fetched {0} of {1} total", totalLoaded, config.ChannelStructureEntities.Count)); }while (config.ChannelStructureEntities.Count > totalLoaded); } catch (Exception ex) { _context.Log(LogLevel.Error, ex.Message, ex); } }