/// <summary> /// Imports and saves package xml as <see cref="ITemplate"/> /// </summary> /// <param name="element">Xml to import</param> /// <param name="userId">Optional user id</param> /// <returns>An enumrable list of generated Templates</returns> public IEnumerable <ITemplate> ImportTemplates(XElement element, int userId = 0) { var name = element.Name.LocalName; if (name.Equals("Templates") == false && name.Equals("Template") == false) { throw new ArgumentException("The passed in XElement is not valid! It does not contain a root element called 'Templates' for multiple imports or 'Template' for a single import."); } var templates = new List <ITemplate>(); var templateElements = name.Equals("Templates") ? (from doc in element.Elements("Template") select doc).ToList() : new List <XElement> { element.Element("Template") }; var fields = new List <TopologicalSorter.DependencyField <XElement> >(); foreach (XElement tempElement in templateElements) { var dependencies = new List <string>(); var elementCopy = tempElement; //Ensure that the Master of the current template is part of the import, otherwise we ignore this dependency as part of the dependency sorting. if (elementCopy.Element("Master") != null && string.IsNullOrEmpty(elementCopy.Element("Master").Value) == false && templateElements.Any(x => x.Element("Alias").Value == elementCopy.Element("Master").Value)) { dependencies.Add(elementCopy.Element("Master").Value); } else if (elementCopy.Element("Master") != null && string.IsNullOrEmpty(elementCopy.Element("Master").Value) == false && templateElements.Any(x => x.Element("Alias").Value == elementCopy.Element("Master").Value) == false) { LogHelper.Info <PackagingService>(string.Format("Template '{0}' has an invalid Master '{1}', so the reference has been ignored.", elementCopy.Element("Alias").Value, elementCopy.Element("Master").Value)); } var field = new TopologicalSorter.DependencyField <XElement> { Alias = elementCopy.Element("Alias").Value, Item = new Lazy <XElement>(() => elementCopy), DependsOn = dependencies.ToArray() }; fields.Add(field); } //Sort templates by dependencies to a potential master template var sortedElements = TopologicalSorter.GetSortedItems(fields); foreach (var templateElement in sortedElements) { var templateName = templateElement.Element("Name").Value; var alias = templateElement.Element("Alias").Value; var design = templateElement.Element("Design").Value; var masterElement = templateElement.Element("Master"); var isMasterPage = IsMasterPageSyntax(design); var path = isMasterPage ? MasterpagePath(alias) : ViewPath(alias); var existingTemplate = _fileService.GetTemplate(alias) as Template; var template = existingTemplate ?? new Template(path, templateName, alias); template.Content = design; if (masterElement != null && string.IsNullOrEmpty(masterElement.Value) == false) { template.MasterTemplateAlias = masterElement.Value; var masterTemplate = templates.FirstOrDefault(x => x.Alias == masterElement.Value); if (masterTemplate != null) { template.MasterTemplateId = new Lazy <int>(() => masterTemplate.Id); } } templates.Add(template); } if (templates.Any()) { _fileService.SaveTemplate(templates, userId); } return(templates); }
/// <summary> /// Imports and saves package xml as <see cref="ITemplate"/> /// </summary> /// <param name="element">Xml to import</param> /// <param name="userId">Optional user id</param> /// <returns>An enumrable list of generated Templates</returns> public IEnumerable<ITemplate> ImportTemplates(XElement element, int userId = 0) { var name = element.Name.LocalName; if (name.Equals("Templates") == false && name.Equals("Template") == false) { throw new ArgumentException("The passed in XElement is not valid! It does not contain a root element called 'Templates' for multiple imports or 'Template' for a single import."); } var templates = new List<ITemplate>(); var templateElements = name.Equals("Templates") ? (from doc in element.Elements("Template") select doc).ToList() : new List<XElement> { element.Element("Template") }; var fields = new List<TopologicalSorter.DependencyField<XElement>>(); foreach (XElement tempElement in templateElements) { var dependencies = new List<string>(); var elementCopy = tempElement; //Ensure that the Master of the current template is part of the import, otherwise we ignore this dependency as part of the dependency sorting. if (elementCopy.Element("Master") != null && string.IsNullOrEmpty(elementCopy.Element("Master").Value) == false && templateElements.Any(x => x.Element("Alias").Value == elementCopy.Element("Master").Value)) { dependencies.Add(elementCopy.Element("Master").Value); } else if (elementCopy.Element("Master") != null && string.IsNullOrEmpty(elementCopy.Element("Master").Value) == false && templateElements.Any(x => x.Element("Alias").Value == elementCopy.Element("Master").Value) == false) { LogHelper.Info<PackagingService>(string.Format("Template '{0}' has an invalid Master '{1}', so the reference has been ignored.", elementCopy.Element("Alias").Value, elementCopy.Element("Master").Value)); } var field = new TopologicalSorter.DependencyField<XElement> { Alias = elementCopy.Element("Alias").Value, Item = new Lazy<XElement>(() => elementCopy), DependsOn = dependencies.ToArray() }; fields.Add(field); } //Sort templates by dependencies to a potential master template var sortedElements = TopologicalSorter.GetSortedItems(fields); foreach (var templateElement in sortedElements) { var templateName = templateElement.Element("Name").Value; var alias = templateElement.Element("Alias").Value; var design = templateElement.Element("Design").Value; var masterElement = templateElement.Element("Master"); var isMasterPage = IsMasterPageSyntax(design); var path = isMasterPage ? MasterpagePath(alias) : ViewPath(alias); var existingTemplate = _fileService.GetTemplate(alias) as Template; var template = existingTemplate ?? new Template(path, templateName, alias); template.Content = design; if (masterElement != null && string.IsNullOrEmpty(masterElement.Value) == false) { template.MasterTemplateAlias = masterElement.Value; var masterTemplate = templates.FirstOrDefault(x => x.Alias == masterElement.Value); if (masterTemplate != null) template.MasterTemplateId = new Lazy<int>(() => masterTemplate.Id); } templates.Add(template); } if (templates.Any()) _fileService.SaveTemplate(templates, userId); return templates; }
/// <summary> /// reads all documentTypes in a given folder and adds them to umbraco /// /// it then recurses into any subfolders. this means we can recreate the /// document types for a umbraco install, making sure we create the parent /// document types first, (in the top folders) that way we get no failures /// based on dependency, /// /// because we are doing this with individual xml files, it's simpler code /// than how the package manager does it with one massive XML file. /// </summary> /// <param name="path"></param> private static void ReadFromDisk(string path) { var docTypes = GetImportDocTypes(path, new Dictionary <string, XElement>()); // here we need to sort - // this is very similar to the import routine, but // because we only want to import new things, we need to ensure // that the order of the things we are importing is maintained. // (we might not be importing something that is a dependency - because // it's already there) var fields = new List <TopologicalSorter.DependencyField <XElement> >(); foreach (var item in docTypes) { LogHelper.Debug <SyncDocType>("Sorting DocType order: {0}", () => item.Key); var dependencies = new List <string>(); var doctype = item.Value; if (doctype.Element("Master") != null && string.IsNullOrEmpty(doctype.Element("Master").Value) == false) { var master = doctype.Element("Master").Value; LogHelper.Debug <SyncDocType>("{0}: Checking Dependency {1}", () => item.Key, () => master); if (docTypes.ContainsKey(master)) { LogHelper.Debug <SyncDocType>("{0}: Adding Dependency {1}", () => item.Key, () => master); dependencies.Add(master); } else if (!DocTypeExists(master)) { LogHelper.Info <SyncDocType>("{0} : Cannot find the master type {1}, either in the import or the site", () => doctype.Element("Info").Element("Alias").Value, () => master); } } // composistion types.. var compElement = doctype.Element("Info").Element("Compositions"); if (compElement != null && compElement.HasElements) { var composistions = compElement.Elements("Composition"); if (composistions.Any()) { foreach (var comp in composistions) { LogHelper.Debug <SyncDocType>("{0}: Checking Dependency {1}", () => item.Key, () => comp.Value); if (docTypes.ContainsKey(comp.Value)) { LogHelper.Debug <SyncDocType>("{0}: Adding Dependency {1}", () => item.Key, () => comp.Value); dependencies.Add(comp.Value); } else if (!DocTypeExists(comp.Value)) { LogHelper.Warn <SyncDocType>("{0} : Cannot find one of the composite types {1} either in the import or the site, this import will likely fail", () => doctype.Element("Info").Element("Alias").Value, () => comp.Value); // again we should check. } } } } var field = new TopologicalSorter.DependencyField <XElement> { Alias = doctype.Element("Info").Element("Alias").Value, Item = new Lazy <XElement>(() => doctype), DependsOn = dependencies.ToArray() }; fields.Add(field); } LogHelper.Debug <SyncDocType>("Processing {0} sorted doctypes", () => fields.Count()); // now go through the doctypes - in their sorted order... foreach (var node in TopologicalSorter.GetSortedItems(fields).ToList()) { LogHelper.Info <SyncDocType>("Updating DocType {0}", () => node.Element("Info").Element("Alias").Value); if (node.ImportContentType() != null) { if (!updated.ContainsKey(node.Element("Info").Element("Alias").Value)) { updated.Add(node.Element("Info").Element("Alias").Value, node); } else { LogHelper.Info <SyncDocType>("WARNING: Multiple DocTypes detected - check your uSync folder"); } } } }