public override SyncAttempt <IMedia> DeserializeSecondPass(IMedia item, XElement node, SyncSerializerOptions options) { var propertyAttempt = DeserializeProperties(item, node, options); if (!propertyAttempt.Success) { return(SyncAttempt <IMedia> .Fail(item.Name, ChangeType.Fail, "Failed to save properties", propertyAttempt.Exception)); } var info = node.Element("Info"); var sortOrder = info.Element("SortOrder").ValueOrDefault(-1); HandleSortOrder(item, sortOrder); var trashed = info.Element("Trashed").ValueOrDefault(false); HandleTrashedState(item, trashed); var attempt = mediaService.Save(item); if (!attempt.Success) { return(SyncAttempt <IMedia> .Fail(item.Name, ChangeType.Fail, "")); } // setting the saved flag on the attempt to true, stops base classes from saving the item. return(SyncAttempt <IMedia> .Succeed(item.Name, item, ChangeType.NoChange, propertyAttempt.Status, true, propertyAttempt.Result)); }
/// <summary> /// Get all the files in a folder and return them sorted by their level /// </summary> private IList <LeveledFile> GetLevelOrderedFiles(string folder, IList <uSyncAction> actions) { List <LeveledFile> nodes = new List <LeveledFile>(); var files = syncFileService.GetFiles(folder, "*.config"); foreach (var file in files) { try { var node = LoadNode(file); if (node != null) { nodes.Add(new LeveledFile { Level = node.GetLevel(), File = file }); } } catch (XmlException ex) { // one of the files is wrong. (do we stop or carry on) logger.Warn(handlerType, $"Error loading file: {file} [{ex.Message}]"); actions.Add(uSyncActionHelper <TObject> .SetAction( SyncAttempt <TObject> .Fail(Path.GetFileName(file), ChangeType.Fail, $"Failed to Load: {ex.Message}"), file, Guid.Empty, this.Alias, false)); } } return(nodes.OrderBy(x => x.Level).ToList()); }
public override SyncAttempt <IMedia> DeserializeSecondPass(IMedia item, XElement node, SerializerFlags flags) { var propertyAttempt = DeserializeProperties(item, node); if (!propertyAttempt.Success) { return(SyncAttempt <IMedia> .Fail(item.Name, ChangeType.Fail, "Failed to save properties", propertyAttempt.Exception)); } var info = node.Element("Info"); var sortOrder = info.Element("SortOrder").ValueOrDefault(-1); HandleSortOrder(item, sortOrder); var trashed = info.Element("Trashed").ValueOrDefault(false); HandleTrashedState(item, trashed); var attempt = mediaService.Save(item); if (!attempt.Success) { return(SyncAttempt <IMedia> .Fail(item.Name, ChangeType.Fail, "")); } // we return no-change so we don't trigger the second save return(SyncAttempt <IMedia> .Succeed(item.Name, item, ChangeType.NoChange, propertyAttempt.Status)); }
public override SyncAttempt <IContent> DeserializeSecondPass(IContent item, XElement node, SerializerFlags flags) { var attempt = DeserializeProperties(item, node); if (!attempt.Success) { return(SyncAttempt <IContent> .Fail(item.Name, ChangeType.ImportFail, attempt.Exception)); } // sort order var sortOrder = node.Element("Info").Element("SortOrder").ValueOrDefault(-1); HandleSortOrder(item, sortOrder); var trashed = node.Element("Info").Element("Trashed").ValueOrDefault(false); HandleTrashedState(item, trashed); // published status // this does the last save and publish var saveAttempt = DoSaveOrPublish(item, node); if (saveAttempt.Success) { // we say no change back, this stops the core second pass function from saving // this item (which we have just done with DoSaveOrPublish) return(SyncAttempt <IContent> .Succeed(item.Name, item, ChangeType.NoChange, attempt.Status)); } return(SyncAttempt <IContent> .Fail(item.Name, item, ChangeType.ImportFail, $"{saveAttempt.Result} {attempt.Status}")); }
/// <summary> /// Get all the files in a folder and return them sorted by their level /// </summary> private IList <LeveledFile> GetLevelOrderedFiles(string folder, IList <uSyncAction> actions) { List <LeveledFile> nodes = new List <LeveledFile>(); var files = syncFileService.GetFiles(folder, $"*.{this.uSyncConfig.Settings.DefaultExtension}"); foreach (var file in files) { try { var node = LoadNode(file); if (node != null) { nodes.Add(new LeveledFile { Level = (node.GetLevel() * 1000) + node.GetItemSortOrder(), // will hopefully let us put things in sort order in one go. File = file }); // debug. logger.LogDebug("{file} {level}", file, (node.GetLevel() * 1000) + node.GetItemSortOrder()); } } catch (XmlException ex) { // one of the files is wrong. (do we stop or carry on) logger.LogWarning($"Error loading file: {file} [{ex.Message}]"); actions.Add(uSyncActionHelper <TObject> .SetAction( SyncAttempt <TObject> .Fail(Path.GetFileName(file), ChangeType.Fail, $"Failed to Load: {ex.Message}"), file, Guid.Empty, this.Alias, false)); } } return(nodes.OrderBy(x => x.Level).ToList()); }
private SyncAttempt <XElement> ExportMemberType(string key) { var _typeService = ApplicationContext.Current.Services.MemberTypeService; var item = _typeService.Get(key); if (item != null) { return(uSyncCoreContext.Instance.MemberTypeSerializer.Serialize(item)); } return(SyncAttempt <XElement> .Fail(key, ChangeType.Export, "item not found")); }
protected override SyncAttempt <TObject> CanDeserialize(XElement node, SerializerFlags flags) { if (flags.HasFlag(SerializerFlags.FailMissingParent)) { // check the parent exists. if (!this.HasParentItem(node)) { return(SyncAttempt <TObject> .Fail(node.GetAlias(), ChangeType.ParentMissing, $"The parent node for this item is missing, and config is set to not import when a parent is missing")); } } return(SyncAttempt <TObject> .Succeed("No check", ChangeType.NoChange)); }
private SyncAttempt <XElement> ExportDictionaryItem(string key) { var _typeService = ApplicationContext.Current.Services.LocalizationService; var item = _typeService.GetDictionaryItemByKey(key); if (item != null) { return(uSyncCoreContext.Instance.DictionarySerializer.Serialize(item)); } return(SyncAttempt <XElement> .Fail(key, ChangeType.Export, "item not found")); }
protected override SyncAttempt <IDomain> DeserializeCore(XElement node, SyncSerializerOptions options) { var item = FindOrCreate(node); var info = node?.Element("Info"); if (info == null) { return(SyncAttempt <IDomain> .Fail(node.GetAlias(), default(IDomain), ChangeType.Fail, "Missing info section in xml", new ArgumentNullException("Info", "Missing Info Section in XML"))); } var isoCode = info.Element("Language").ValueOrDefault(string.Empty) ?? string.Empty; var changes = new List <uSyncChange>(); if (!string.IsNullOrWhiteSpace(isoCode)) { var language = localizationService.GetLanguageByIsoCode(isoCode); if (language != null && item.LanguageId != language.Id) { changes.AddUpdate("Id", item.LanguageId, language.Id); item.LanguageId = language.Id; } } var rootItem = default(IContent); var rootKey = info.Element("Root")?.Attribute("Key").ValueOrDefault(Guid.Empty) ?? Guid.Empty; if (rootKey != Guid.Empty) { rootItem = contentService.GetById(rootKey); } if (rootItem == default(IContent)) { var rootName = info.Element("Root").ValueOrDefault(string.Empty); if (rootName != string.Empty) { rootItem = FindByPath(rootName.ToDelimitedList("/")); } } if (rootItem != default(IContent) && item.RootContentId != rootItem.Id) { changes.AddUpdate("RootItem", item.RootContentId, rootItem.Id); item.RootContentId = rootItem.Id; } return(SyncAttempt <IDomain> .Succeed(item.DomainName, item, ChangeType.Import, changes)); }
public override SyncAttempt <IContent> DeserializeSecondPass(IContent item, XElement node, SyncSerializerOptions options) { var attempt = DeserializeProperties(item, node, options); if (!attempt.Success) { return(SyncAttempt <IContent> .Fail(item.Name, ChangeType.ImportFail, attempt.Exception)); } var changes = attempt.Result; // sort order var sortOrder = node.Element("Info").Element("SortOrder").ValueOrDefault(-1); changes.AddNotNull(HandleSortOrder(item, sortOrder)); var trashed = node.Element("Info").Element("Trashed").ValueOrDefault(false); changes.AddNotNull(HandleTrashedState(item, trashed)); var publishTimer = Stopwatch.StartNew(); // published status // this does the last save and publish var saveAttempt = DoSaveOrPublish(item, node, options); if (saveAttempt.Success) { var message = attempt.Status; if (publishTimer.ElapsedMilliseconds > 10000) { message += $" (Slow publish {publishTimer.ElapsedMilliseconds}ms)"; } // we say no change back, this stops the core second pass function from saving // this item (which we have just done with DoSaveOrPublish) return(SyncAttempt <IContent> .Succeed(item.Name, item, ChangeType.NoChange, message, true, changes)); } return(SyncAttempt <IContent> .Fail(item.Name, item, ChangeType.ImportFail, $"{saveAttempt.Result} {attempt.Status}")); }
internal override SyncAttempt <XElement> SerializeCore(IDataTypeDefinition item) { try { var node = new XElement(Constants.Packaging.DataTypeNodeName, new XAttribute("Name", item.Name), new XAttribute("Key", item.Key), new XAttribute("Id", item.PropertyEditorAlias), new XAttribute("DatabaseType", item.DatabaseType.ToString()) ); node.Add(SerializePreValues(item, node)); return(SyncAttempt <XElement> .Succeed(item.Name, node, typeof(IDataTypeDefinition), ChangeType.Export)); } catch (Exception ex) { LogHelper.Warn <DataTypeSerializer>("Error Serializing {0}", () => ex.ToString()); return(SyncAttempt <XElement> .Fail(item.Name, typeof(IDataTypeDefinition), ChangeType.Export, "Failed to export", ex)); } }
public override SyncAttempt <IMedia> DeserializeSecondPass(IMedia item, XElement node, SerializerFlags flags) { DeserializeProperties(item, node); var info = node.Element("Info"); var sortOrder = info.Element("SortOrder").ValueOrDefault(-1); if (sortOrder != -1) { item.SortOrder = sortOrder; } var trashed = info.Element("Trashed").ValueOrDefault(false); if (trashed) { if (!item.Trashed) { mediaService.MoveToRecycleBin(item); } return(SyncAttempt <IMedia> .Succeed(item.Name, ChangeType.Import)); } if (item.Trashed) { // remove from bin. // ? } var attempt = mediaService.Save(item); if (attempt.Success) { return(SyncAttempt <IMedia> .Succeed(item.Name, ChangeType.Import)); } return(SyncAttempt <IMedia> .Fail(item.Name, ChangeType.Fail, "")); }
virtual public SyncAttempt <TObject> Import(string filePath, HandlerSettings config, SerializerFlags flags) { try { syncFileService.EnsureFileExists(filePath); using (var stream = syncFileService.OpenRead(filePath)) { var node = XElement.Load(stream); var attempt = serializer.Deserialize(node, flags); return(attempt); } } catch (FileNotFoundException notFoundException) { return(SyncAttempt <TObject> .Fail(Path.GetFileName(filePath), ChangeType.Fail, $"File not found {notFoundException.Message}")); } catch (Exception ex) { return(SyncAttempt <TObject> .Fail(Path.GetFileName(filePath), ChangeType.Fail, $"Import Fail: {ex.Message}")); } }
internal override SyncAttempt <ILanguage> DeserializeCore(XElement node) { var culture = node.Attribute("CultureAlias"); var fName = node.Attribute("FriendlyName"); if (culture == null || fName == null) { return(SyncAttempt <ILanguage> .Fail(node.NameFromNode(), ChangeType.Import, "missing Alias or Name")); } // by name ILanguage item = _localizationService.GetLanguageByCultureCode(fName.Value); // by iso code if (item == null) { item = _localizationService.GetLanguageByIsoCode(culture.Value); } // create a new one if (item == null) { item = new Language(culture.Value); } // all that failed if (item == null) { return(SyncAttempt <ILanguage> .Fail(node.NameFromNode(), ChangeType.Import, "Unable to import language")); } // it worked update stuff.. item.IsoCode = culture.Value; item.CultureName = fName.Value; _localizationService.Save(item); return(SyncAttempt <ILanguage> .Succeed(item.CultureName, item, ChangeType.Import)); }
public override SyncAttempt <IContent> DeserializeSecondPass(IContent item, XElement node, SerializerFlags flags) { DeserializeProperties(item, node); // sort order var sortOrder = node.Element("Info").Element("SortOrder").ValueOrDefault(-1); if (sortOrder != -1) { item.SortOrder = sortOrder; } // published status // this does the last save and publish if (DoSaveOrPublish(item, node)) { return(SyncAttempt <IContent> .Succeed(item.Name, ChangeType.Import)); } return(SyncAttempt <IContent> .Fail(item.Name, ChangeType.ImportFail, "")); // second pass, is when we do the publish and stuff. }
protected override SyncAttempt <FieldPreValueSource> DeserializeCore(XElement node, SyncSerializerOptions options) { var item = FindItem(node); if (item == null) { item = new FieldPreValueSource(); item.Id = node.GetKey(); } var info = node.Element("Info"); if (info != null) { // validate that the prevalue source type exists (can be added in custom code) var fieldTypeId = info.Element("FieldPreValueSourceTypeId").ValueOrDefault(Guid.Empty); if (!fieldPreValueSourceTypes.Any(x => x.Id == fieldTypeId)) { return(SyncAttempt <FieldPreValueSource> .Fail(node.GetAlias(), ChangeType.Fail, new Exception("FieldType cannot be found (missing a PreValueProvider?)"))); } item.Name = info.Element("Name").ValueOrDefault(node.GetAlias()); item.FieldPreValueSourceTypeId = fieldTypeId; } var settings = node.Element("Settings").ValueOrDefault(string.Empty); if (!string.IsNullOrWhiteSpace(settings)) { item.Settings = JsonConvert.DeserializeObject <Dictionary <string, string> >(settings); } return(SyncAttempt <FieldPreValueSource> .Succeed(item.Name, item, ChangeType.Import)); }
protected override SyncAttempt <ITemplate> DeserializeCore(XElement node, SyncSerializerOptions options) { var key = node.GetKey(); var alias = node.GetAlias(); var name = node.Element("Name").ValueOrDefault(string.Empty); var item = default(ITemplate); var details = new List <uSyncChange>(); if (key != Guid.Empty) { item = fileService.GetTemplate(key); } if (item == null) { item = fileService.GetTemplate(alias); } if (item == null) { // create var templatePath = IOHelper.MapPath(SystemDirectories.MvcViews + "/" + alias.ToSafeFileName() + ".cshtml"); if (System.IO.File.Exists(templatePath)) { logger.Debug <TemplateSerializer>("Reading {0} contents", templatePath); var content = System.IO.File.ReadAllText(templatePath); item = new Template(name, alias); item.Path = templatePath; item.Content = content; details.AddNew(alias, alias, "Template"); } else { // template is missing // we can't create return(SyncAttempt <ITemplate> .Fail(name, ChangeType.Import, "The template '.cshtml' file is missing.")); } } if (item == null) { // creating went wrong return(SyncAttempt <ITemplate> .Fail(name, ChangeType.Import, "Failed to create template")); } if (item.Key != key) { details.AddUpdate("Key", item.Key, key); item.Key = key; } if (item.Name != name) { details.AddUpdate("Name", item.Name, name); item.Name = name; } if (item.Alias != alias) { details.AddUpdate("Alias", item.Alias, alias); item.Alias = alias; } //var master = node.Element("Parent").ValueOrDefault(string.Empty); //if (master != string.Empty) //{ // var masterItem = fileService.GetTemplate(master); // if (masterItem != null) // item.SetMasterTemplate(masterItem); //} // Deserialize now takes care of the save. // fileService.SaveTemplate(item); return(SyncAttempt <ITemplate> .Succeed(item.Name, item, ChangeType.Import, details)); }
internal override SyncAttempt <IMedia> DeserializeCore(XElement node, int parentId, bool forceUpdate) { var nodeGuid = node.Attribute("guid"); if (nodeGuid == null) { return(SyncAttempt <IMedia> .Fail(node.NameFromNode(), ChangeType.Import, "No guid, in xml")); } Guid guid = new Guid(nodeGuid.Value); var name = node.Attribute("nodeName").Value; string mediaTypeAlias = node.Attribute("nodeTypeAlias").Value; var update = node.Attribute("updated").ValueOrDefault(DateTime.Now); var item = _mediaService.GetById(guid); if (item == null || item.Trashed) { item = _mediaService.CreateMedia(name, parentId, mediaTypeAlias); } else { if (!forceUpdate) { if (DateTime.Compare(update, item.UpdateDate.ToLocalTime()) < 0) { return(SyncAttempt <IMedia> .Succeed(item.Name, item, ChangeType.NoChange)); } } } if (item != null) { if (item.Key != guid) { item.Key = guid; } if (item.Name != name) { item.Name = name; } if (item.ParentId != parentId) { item.ParentId = parentId; } /* * properties are set in second pass, for speed we don't do it here. */ /* * var properties = node.Elements().Where(x => x.Attribute("isDoc") == null); * foreach (var property in properties) * { * var propertyTypeAlias = property.Name.LocalName; * if (item.HasProperty(propertyTypeAlias)) * { * var propType = item.Properties[propertyTypeAlias].PropertyType; * var newValue = GetImportIds(propType, GetImportXml(property)); * * LogHelper.Debug<Events>("#### Setting property: [{0}] to {1}", () => propertyTypeAlias, () => newValue); * item.SetValue(propertyTypeAlias, newValue); * } * } */ _mediaService.Save(item); } return(SyncAttempt <IMedia> .Succeed(item.Name, item, ChangeType.Import)); }
/// <summary> /// this is the simple interface, based purely on level, /// we could get clever (like dependency trees for content types) /// /// but that would have to be implimented lower down (and it doesn't /// really matter for things in containers only things that parent others). /// </summary> /// <param name="folder"></param> /// <param name="force"></param> /// <param name="updates"></param> /// <returns></returns> protected override IEnumerable <uSyncAction> ImportFolder(string folder, HandlerSettings config, Dictionary <string, TObject> updates, bool force, SyncUpdateCallback callback) { // if not using flat, then directory structure is doing // this for us. if (config.UseFlatStructure == false) { return(base.ImportFolder(folder, config, updates, force, callback)); } List <uSyncAction> actions = new List <uSyncAction>(); var files = syncFileService.GetFiles(folder, "*.config"); List <LeveledFile> nodes = new List <LeveledFile>(); callback?.Invoke("Calculating import order", 0, 1); logger.Verbose(handlerType, "Calculating import order"); foreach (var file in files) { try { var node = LoadNode(file); if (node != null) { nodes.Add(new LeveledFile { Level = node.GetLevel(), File = file }); } } catch (XmlException ex) { // one of the files is wrong. (do we stop or carry on) logger.Warn(handlerType, $"Error loading file: {file} [{ex.Message}]"); actions.Add(uSyncActionHelper <TObject> .SetAction( SyncAttempt <TObject> .Fail(Path.GetFileName(file), ChangeType.Fail, $"Failed to Load: {ex.Message}"), file, false)); } } // loaded - now process. var flags = SerializerFlags.None; if (force) { flags |= SerializerFlags.Force; } if (config.BatchSave) { flags |= SerializerFlags.DoNotSave; } var cleanMarkers = new List <string>(); foreach (var item in nodes.OrderBy(x => x.Level).Select((Node, Index) => new { Node, Index })) { var filename = Path.GetFileNameWithoutExtension(item.Node.File); callback?.Invoke($"{filename}", item.Index, nodes.Count); logger.Verbose(handlerType, "{Index} Importing: {File}, [Level {Level}]", item.Index, filename, item.Node.Level); var attempt = Import(item.Node.File, config, flags); if (attempt.Success) { if (attempt.Change == ChangeType.Clean) { cleanMarkers.Add(item.Node.File); } else if (attempt.Item != null) { updates.Add(item.Node.File, attempt.Item); } } actions.Add(uSyncActionHelper <TObject> .SetAction(attempt, item.Node.File, IsTwoPass)); } if (flags.HasFlag(SerializerFlags.DoNotSave) && updates.Any()) { // bulk save - should be the fastest way to do this callback?.Invoke($"Saving {updates.Count()} changes", 1, 1); serializer.Save(updates.Select(x => x.Value)); } var folders = syncFileService.GetDirectories(folder); foreach (var children in folders) { actions.AddRange(ImportFolder(children, config, updates, force, callback)); } if (actions.All(x => x.Success)) { // LINQ // actions.AddRange(cleanMarkers.Select(x => CleanFolder(x)).SelectMany(a => a)); // only if there are no fails. // then we consider the folder safe to clean foreach (var cleanfile in cleanMarkers) { actions.AddRange(CleanFolder(cleanfile, false, config.UseFlatStructure)); } // remove the actual cleans (they will have been replaced by the deletes actions.RemoveAll(x => x.Change == ChangeType.Clean); } callback?.Invoke("", 1, 1); return(actions); }
internal override SyncAttempt <IContent> DeserializeCore(XElement node, int parentId, bool forceUpdate = false) { var nodeGuid = node.Attribute("guid"); if (nodeGuid == null) { return(SyncAttempt <IContent> .Fail(node.NameFromNode(), ChangeType.Import, "No Guid in XML")); } Guid guid = new Guid(nodeGuid.Value); var name = node.Attribute("nodeName").Value; var type = node.Attribute("nodeTypeAlias").Value; var templateAlias = node.Attribute("templateAlias").Value; var sortOrder = int.Parse(node.Attribute("sortOrder").Value); var published = bool.Parse(node.Attribute("published").Value); // because later set the guid, we are going for a match at this point var item = _contentService.GetById(guid); if (item == null) { item = _contentService.CreateContent(name, parentId, type); } else { // update is different for content, we go on publish times.. if (!forceUpdate) { DateTime updateTime = node.Attribute("updated").ValueOrDefault(DateTime.Now); if (DateTime.Compare(updateTime, item.UpdateDate.ToLocalTime()) <= 0) { // the import is older than the content on this site; return(SyncAttempt <IContent> .Succeed(item.Name, item, ChangeType.NoChange)); } } } if (item == null) { return(SyncAttempt <IContent> .Fail(node.NameFromNode(), ChangeType.ImportFail, "Cannot find or create content item")); } // if it's in the trash remove it. if (item.Trashed) { item.ChangeTrashedState(false); } var template = ApplicationContext.Current.Services.FileService.GetTemplate(templateAlias); if (template != null) { item.Template = template; } item.Key = guid; item.SortOrder = sortOrder; item.Name = name; if (item.ParentId != parentId) { item.ParentId = parentId; } var properties = node.Elements().Where(x => x.Attribute("isDoc") == null); foreach (var property in properties) { var propertyTypeAlias = property.Name.LocalName; if (item.HasProperty(propertyTypeAlias)) { var propType = item.Properties[propertyTypeAlias].PropertyType; var newValue = GetImportIds(propType, GetImportXml(property)); LogHelper.Debug <Events>("#### Setting property: [{0}] to {1}", () => propertyTypeAlias, () => newValue); item.SetValue(propertyTypeAlias, newValue); } } PublishOrSave(item, published); return(SyncAttempt <IContent> .Succeed(item.Name, item, ChangeType.Import)); }
protected override SyncAttempt <IMedia> DeserializeCore(XElement node, SyncSerializerOptions options) { var attempt = FindOrCreate(node); if (!attempt.Success) { throw attempt.Exception; } var item = attempt.Result; var details = new List <uSyncChange>(); details.AddRange(DeserializeBase(item, node, options)); if (node.Element("Info") != null) { var trashed = node.Element("Info").Element("Trashed").ValueOrDefault(false); details.AddNotNull(HandleTrashedState(item, trashed)); } var propertyAttempt = DeserializeProperties(item, node, options); if (!propertyAttempt.Success) { return(SyncAttempt <IMedia> .Fail(item.Name, item, ChangeType.Fail, "Failed to save properties", propertyAttempt.Exception)); } var info = node.Element("Info"); var sortOrder = info.Element("SortOrder").ValueOrDefault(-1); HandleSortOrder(item, sortOrder); if (details.HasWarning() && options.FailOnWarnings()) { // Fail on warning. means we don't save or publish because something is wrong ? return(SyncAttempt <IMedia> .Fail(item.Name, item, ChangeType.ImportFail, "Failed with warnings", details, new Exception("Import failed because of warnings, and fail on warnings is true"))); } var saveAttempt = mediaService.Save(item); if (!saveAttempt.Success) { var errors = saveAttempt.Result?.EventMessages?.FormatMessages() ?? ""; return(SyncAttempt <IMedia> .Fail(item.Name, item, ChangeType.Fail, errors, saveAttempt.Exception)); } // add warning messages if things are missing var message = ""; if (details.Any(x => x.Change == ChangeDetailType.Warning)) { message += $" with warning(s)"; } // setting the saved flag on the attempt to true, stops base classes from saving the item. return(SyncAttempt <IMedia> .Succeed(item.Name, item, ChangeType.Import, "", true, propertyAttempt.Result)); }
internal override SyncAttempt <ITemplate> DeserializeCore(XElement node) { if (node == null || node.Element("Alias") == null || node.Element("Name") == null) { throw new ArgumentException("Bad xml import"); } var alias = node.Element("Alias").ValueOrDefault(string.Empty); if (string.IsNullOrEmpty(alias)) { SyncAttempt <ITemplate> .Fail(node.NameFromNode(), ChangeType.Import, "No Alias node in xml"); } LogHelper.Debug <Events>("# Importing Template : {0}", () => alias); var name = node.Element("Name").ValueOrDefault(string.Empty); var item = _fileService.GetTemplate(alias); if (item == null) { var templatePath = IOHelper.MapPath(SystemDirectories.MvcViews + "/" + alias.ToSafeFileName() + ".cshtml"); if (!System.IO.File.Exists(templatePath)) { templatePath = IOHelper.MapPath(SystemDirectories.Masterpages + "/" + alias.ToSafeFileName() + ".master"); if (!System.IO.File.Exists(templatePath)) { // cannot find the master for this.. templatePath = string.Empty; LogHelper.Warn <TemplateSerializer>("Cannot find underling template file, so we cannot create the template"); } } if (!string.IsNullOrEmpty(templatePath)) { var content = System.IO.File.ReadAllText(templatePath); item = new Template(name, alias); item.Path = templatePath; item.Content = content; } else { LogHelper.Warn <TemplateSerializer>("Can't get a template path?"); return(SyncAttempt <ITemplate> .Fail(name, ChangeType.Import, "Failed to generate template path")); } } if (item == null) { LogHelper.Warn <TemplateSerializer>("Cannot create the template, something missing?"); return(SyncAttempt <ITemplate> .Fail(name, ChangeType.Import, "Item create fail")); } if (node.Element("Name").Value != item.Name) { item.Name = node.Element("Name").Value; } if (node.Element("Master") != null) { var masterName = node.Element("Master").Value; if (!string.IsNullOrEmpty(masterName)) { var master = _fileService.GetTemplate(masterName); if (master != null) { item.SetMasterTemplate(master); } } } var key = node.Element("Key").ValueOrDefault(Guid.Empty); if (key != Guid.Empty) { item.Key = key; } _fileService.SaveTemplate(item); return(SyncAttempt <ITemplate> .Succeed(item.Name, item, ChangeType.Import)); }
protected override SyncAttempt <ITemplate> DeserializeCore(XElement node, SyncSerializerOptions options) { var key = node.GetKey(); var alias = node.GetAlias(); var name = node.Element("Name").ValueOrDefault(string.Empty); var item = default(ITemplate); var details = new List <uSyncChange>(); if (key != Guid.Empty) { item = fileService.GetTemplate(key); } if (item == null) { item = fileService.GetTemplate(alias); } if (item == null) { item = new Template(shortStringHelper, name, alias); details.AddNew(alias, alias, "Template"); if (ShouldGetContentFromNode(node, options)) { logger.LogDebug("Getting content for Template from XML"); item.Content = GetContentFromConfig(node); } else { logger.LogDebug("Loading template content from disk"); var templatePath = ViewPath(alias); if (_viewFileSystem.FileExists(templatePath)) { logger.LogDebug("Reading {0} contents", templatePath); item.Content = GetContentFromFile(templatePath); item.Path = templatePath; } else { if (!options.GetSetting <bool>("UsingRazorViews", false)) { // template is missing // we can't create logger.LogWarning("Failed to create template {path} the local file is missing", templatePath); return(SyncAttempt <ITemplate> .Fail(name, ChangeType.Import, $"The template {templatePath} file is missing.")); } else { // template is not on disk, we could use the viewEngine to find the view // if this finds the view it tells us that the view is somewhere else ? logger.LogDebug("Failed to find content, but UsingRazorViews so will create anyway, then delete the file"); item.Content = $"<!-- [uSyncMarker:{this.Id}] template content - will be removed -->"; } } } } if (item == null) { // creating went wrong logger.LogWarning("Failed to create template"); return(SyncAttempt <ITemplate> .Fail(name, ChangeType.Import, "Failed to create template")); } if (item.Key != key) { details.AddUpdate("Key", item.Key, key); item.Key = key; } if (item.Name != name) { details.AddUpdate("Name", item.Name, name); item.Name = name; } if (item.Alias != alias) { details.AddUpdate("Alias", item.Alias, alias); item.Alias = alias; } if (ShouldGetContentFromNode(node, options)) { var content = GetContentFromConfig(node); if (content != item.Content) { details.AddUpdate("Content", item.Content, content); item.Content = content; } } //var master = node.Element("Parent").ValueOrDefault(string.Empty); //if (master != string.Empty) //{ // var masterItem = fileService.GetTemplate(master); // if (masterItem != null) // item.SetMasterTemplate(masterItem); //} // Deserialize now takes care of the save. // fileService.SaveTemplate(item); return(SyncAttempt <ITemplate> .Succeed(item.Name, item, ChangeType.Import, details)); }
/// <summary> /// this is the simple interface, based purely on level, /// we could get clever (like dependency trees for content types) /// /// but that would have to be implimented lower down (and it doesn't /// really matter for things in containers only things that parent others). /// </summary> /// <param name="folder"></param> /// <param name="force"></param> /// <param name="updates"></param> /// <returns></returns> protected override IEnumerable <uSyncAction> ImportFolder(string folder, HandlerSettings config, Dictionary <string, TObject> updates, bool force, SyncUpdateCallback callback) { // if not using flat, then directory structure is doing // this for us. if (config.UseFlatStructure == false) { return(base.ImportFolder(folder, config, updates, force, callback)); } List <uSyncAction> actions = new List <uSyncAction>(); var files = syncFileService.GetFiles(folder, "*.config"); List <LeveledFile> nodes = new List <LeveledFile>(); callback?.Invoke("Calculating import order", 0, 1); foreach (var file in files) { try { var node = LoadNode(file); if (node != null) { nodes.Add(new LeveledFile { Level = node.GetLevel(), File = file }); } } catch (XmlException ex) { // one of the files is wrong. (do we stop or carry on) logger.Warn <TObject>($"Error loading file: {file} [{ex.Message}]"); actions.Add(uSyncActionHelper <TObject> .SetAction( SyncAttempt <TObject> .Fail(Path.GetFileName(file), ChangeType.Fail, $"Failed to Load: {ex.Message}"), file, false)); } } // loaded - now process. var flags = SerializerFlags.None; if (force) { flags |= SerializerFlags.Force; } if (config.BatchSave) { flags |= SerializerFlags.DoNotSave; } var count = 0; foreach (var node in nodes.OrderBy(x => x.Level)) { count++; callback?.Invoke($"{Path.GetFileName(node.File)}", count, nodes.Count); var attempt = Import(node.File, config, flags); if (attempt.Success && attempt.Item != null) { updates.Add(node.File, attempt.Item); } actions.Add(uSyncActionHelper <TObject> .SetAction(attempt, node.File, IsTwoPass)); } if (flags.HasFlag(SerializerFlags.DoNotSave) && updates.Any()) { // bulk save - should be the fastest way to do this callback?.Invoke($"Saving {updates.Count()} changes", 1, 1); serializer.Save(updates.Select(x => x.Value)); } var folders = syncFileService.GetDirectories(folder); foreach (var children in folders) { actions.AddRange(ImportFolder(children, config, updates, force, callback)); } callback?.Invoke("", 1, 1); return(actions); }
internal override SyncAttempt <IMacro> DeserializeCore(XElement node) { LogHelper.Debug <MacroSerializer>("<< DeserailizeCore Macro"); var item = _packaingService.ImportMacros(node).FirstOrDefault(); // other bits. if (item == null) { return(SyncAttempt <IMacro> .Fail(node.NameFromNode(), ChangeType.Import, "Package Service import failed")); } LogHelper.Debug <MacroSerializer>("<<< DeserailizeCore - General properties"); if (node.Element("name") != null) { item.Name = node.Element("name").Value; } if (node.Element("scriptType") != null) { item.ControlType = node.Element("scriptType").Value; } if (node.Element("scriptAssembly") != null) { item.ControlAssembly = node.Element("scriptAssembly").Value; } if (node.Element("xslt") != null) { item.XsltPath = node.Element("xslt").Value; } if (node.Element("scriptingFile") != null) { item.ScriptPath = node.Element("scriptingFile").Value; } LogHelper.Debug <MacroSerializer>("<<< DeserailizeCore - Defaults"); item.UseInEditor = node.Element("useInEditor").ValueOrDefault(false); item.CacheDuration = node.Element("refreshRate").ValueOrDefault(0); item.CacheByMember = node.Element("cacheByMember").ValueOrDefault(false); item.CacheByPage = node.Element("cacheByPage").ValueOrDefault(false); item.DontRender = node.Element("dontRender").ValueOrDefault(true); LogHelper.Debug <MacroSerializer>("<<< DeserailizeCore - Properties"); List <string> propertiesToRemove = new List <string>(); var properties = node.Element("properties"); if (properties != null && properties.HasElements) { foreach (var property in properties.Elements("property")) { var alias = property.Attribute("alias").Value; var itemProperty = item.Properties.FirstOrDefault(x => string.Equals(x.Alias, alias, StringComparison.OrdinalIgnoreCase) == true); if (itemProperty != null) { LogHelper.Debug <MacroSerializer>("<<< Updating Property: {0}", () => alias); itemProperty.Alias = alias; itemProperty.Name = property.Attribute("name").Value; itemProperty.EditorAlias = property.Attribute("propertyType").Value; } } } foreach (var property in item.Properties) { var nodeProp = properties.Elements("property").FirstOrDefault(x => x.Attribute("alias").Value == property.Alias); if (nodeProp == null) { propertiesToRemove.Add(property.Alias); } } if (propertiesToRemove.Any()) { foreach (var alias in propertiesToRemove) { LogHelper.Debug <MacroSerializer>("<<< Removing Property : {0}", () => alias); item.Properties.Remove(alias); } } LogHelper.Debug <MacroSerializer>("<<< DeserailizeCore - Saving"); ApplicationContext.Current.Services.MacroService.Save(item); LogHelper.Debug <MacroSerializer>("<<< DeserailizeCore - Return"); return(SyncAttempt <IMacro> .Succeed(item.Name, item, ChangeType.Import)); }
/// <summary> /// handles export (needs type folded by filename) /// </summary> /// <param name="args"></param> /// <returns></returns> public async Task <bool> Export(string[] args) { if (args == null || args.Length < 3) { return(false); } var type = args[0].ToLower().Replace("-", ""); var name = args[1].ToLower(); var file = args[2].ToLower(); await Out.WriteLineAsync( string.Format("Exporting: {0} {1} {2}", type, name, file)); var attempt = SyncAttempt <XElement> .Fail("unknown", ChangeType.Export, "Unknown type"); switch (type) { case "contenttype": attempt = ExportContentType(name); break; case "mediatype": attempt = ExportMediaType(name); break; case "datatype": attempt = ExportDataType(name); break; case "dictionaryitem": case "dictionary": attempt = ExportDictionaryItem(name); break; case "language": attempt = ExportLanguage(name); break; case "macro": attempt = ExportMacro(name); break; case "template": attempt = ExportTemplate(name); break; case "membertype": attempt = ExportMemberType(name); break; } if (attempt.Success) { var saveRoot = Path.Combine( new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName, "..\\uSync\\Export\\"); var savePath = Path.Combine(saveRoot, file); if (!Directory.Exists(Path.GetDirectoryName(savePath))) { Directory.CreateDirectory(Path.GetDirectoryName(savePath)); } if (File.Exists(savePath)) { File.Delete(savePath); } attempt.Item.Save(savePath); await Out.WriteLineAsync( string.Format("{0} exported to {1}", name, savePath)); } else { await Out.WriteLineAsync("Failed to export " + name + " " + attempt.Message); } return(true); }
protected override SyncAttempt <IContent> DeserializeCore(XElement node, SyncSerializerOptions options) { var attempt = FindOrCreate(node); if (!attempt.Success) { throw attempt.Exception; } var item = attempt.Result; var details = new List <uSyncChange>(); details.AddRange(DeserializeBase(item, node, options)); if (node.Element("Info") != null) { var trashed = node.Element("Info").Element("Trashed").ValueOrDefault(false); details.AddNotNull(HandleTrashedState(item, trashed)); } details.AddNotNull(DeserializeTemplate(item, node)); var propertiesAttempt = DeserializeProperties(item, node, options); if (!propertiesAttempt.Success) { return(SyncAttempt <IContent> .Fail(item.Name, item, ChangeType.ImportFail, "Failed to deserialize properties", attempt.Exception)); } details.AddRange(propertiesAttempt.Result); // sort order var sortOrder = node.Element("Info").Element("SortOrder").ValueOrDefault(-1); details.AddNotNull(HandleSortOrder(item, sortOrder)); var publishTimer = Stopwatch.StartNew(); if (details.HasWarning() && options.FailOnWarnings()) { // Fail on warning. means we don't save or publish because something is wrong ? return(SyncAttempt <IContent> .Fail(item.Name, item, ChangeType.ImportFail, "Failed with warnings", details, new Exception("Import failed because of warnings, and fail on warnings is true"))); } // published status // this does the last save and publish var saveAttempt = DoSaveOrPublish(item, node, options); if (saveAttempt.Success) { var message = saveAttempt.Result; if (details.Any(x => x.Change == ChangeDetailType.Warning)) { message += $" with warning(s)"; } if (publishTimer.ElapsedMilliseconds > 10000) { message += $" (Slow publish {publishTimer.ElapsedMilliseconds}ms)"; } var changeType = options.GetSetting(uSyncConstants.DefaultSettings.OnlyPublishDirty, uSyncConstants.DefaultSettings.OnlyPublishDirty_Default) && !item.IsDirty() ? ChangeType.NoChange : ChangeType.Import; // we say no change back, this stops the core second pass function from saving // this item (which we have just done with DoSaveOrPublish) return(SyncAttempt <IContent> .Succeed(item.Name, item, changeType, message, true, details)); } else { return(SyncAttempt <IContent> .Fail(item.Name, item, ChangeType.ImportFail, saveAttempt.Result, saveAttempt.Exception)); } }
protected override SyncAttempt <ITemplate> DeserializeCore(XElement node) { var key = node.GetKey(); var alias = node.GetAlias(); var name = node.Element("Name").ValueOrDefault(string.Empty); var item = default(ITemplate); if (key != Guid.Empty) { item = fileService.GetTemplate(key); } if (item == null) { item = fileService.GetTemplate(alias); } if (item == null) { // create var templatePath = IOHelper.MapPath(SystemDirectories.MvcViews + "/" + alias.ToSafeFileName() + ".cshtml"); if (System.IO.File.Exists(templatePath)) { var content = System.IO.File.ReadAllText(templatePath); item = new Template(name, alias); item.Path = templatePath; item.Content = content; } else { // template is missing // we can't create } } if (item == null) { // creating went wrong return(SyncAttempt <ITemplate> .Fail(name, ChangeType.Import, "Failed to create template")); } if (item.Key != key) { item.Key = key; } if (item.Name != name) { item.Name = name; } if (item.Alias != alias) { item.Alias = alias; } var master = node.Element("Parent").ValueOrDefault(string.Empty); if (master != string.Empty) { var masterItem = fileService.GetTemplate(master); if (masterItem != null) { item.SetMasterTemplate(masterItem); } } // Deserialize now takes care of the save. // fileService.SaveTemplate(item); return(SyncAttempt <ITemplate> .Succeed(item.Name, item, ChangeType.Import)); }