/// <summary> /// Audits updates to versionless items /// </summary> /// <param name="repositoryObject"><see cref="T:Tridion.ContentManager.ContentManagement.RepositoryLocalObject" /></param> /// <param name="args">The <see cref="SaveEventArgs" /> instance containing the event data.</param> /// <param name="phase"><see cref="T:Tridion.ContentManager.Extensibility.EventPhases" /></param> private void AuditVersionless(IdentifiableObject identifiableObject, SaveEventArgs args, EventPhases phase) { if (phase == EventPhases.Initiated) { try { // Load the original unmodified item XML from the database IdentifiableObject oldIdentifiableObject = identifiableObject.Session.GetObject(identifiableObject.Id); XElement original = XElement.Parse(oldIdentifiableObject.ToXml().OuterXml); XElement updated = XElement.Parse(identifiableObject.ToXml().OuterXml); XElement difference = XMLDelta.Compare(original, updated); if (difference != null) { AuditContentEdit("Update", identifiableObject, identifiableObject.GetType().Name, new SqlXml(difference.CreateReader())); } else { AuditContentEdit("Update", identifiableObject, identifiableObject.GetType().Name, null); } } catch (Exception ex) { Logger.Write(ex, "TcmEvents.Audit", LoggingCategory.General, TraceEventType.Error); } } }
protected string RunTemplate(Type templateType, IdentifiableObject inputItem, Template template = null) { RenderedItem testRenderedItem = CreateTestRenderedItem(inputItem, template); TestEngine testEngine = new TestEngine(testRenderedItem); Package testPackage = new Package(testEngine); Type inputItemType = inputItem.GetType(); string inputItemName = inputItemType.Name; ContentType inputItemContentType = new ContentType($"tridion/{inputItemType.Name.ToLower()}"); testPackage.PushItem(inputItemName, testPackage.CreateTridionItem(inputItemContentType, inputItem)); ITemplate testTemplate = Activator.CreateInstance(templateType) as ITemplate; Assert.IsNotNull(testTemplate, "testTemplate"); testTemplate.Transform(testEngine, testPackage); Item outputItem = testPackage.GetByName(Package.OutputName); Assert.IsNotNull(outputItem, "outputItem"); string result = outputItem.GetAsString(); Assert.IsNotNull(result, "result"); Console.WriteLine("Output Item:"); Console.WriteLine(result); return(result); }
private void EventHandler(IdentifiableObject subject, EventArgs eventArgs, EventPhases phase) { var record = new Record(); //Set Environment record.Environment = new CMEnvironment { Name = ConfigurationManager.AppSettings.Get("NF4T_CMEnvironmentKey") }; //Set Subject record.Subject = new Subject { TcmId = subject.Id, Title = subject.Title, Type = subject.GetType(), CreationDate = subject.CreationDate, LastModifiedDate = subject.RevisionDate }; //Extract ItemTypeSpecifics if (subject is Component) { var component = subject as Component; record.Subject.SchemaTcmId = component.Schema.Id.ToString(); } //Set Event record.Event = new Event { Type = eventArgs.GetType(), TimeStamp = DateTime.Now }; //Extract ItemTypeSpecifics if (eventArgs is SaveEventArgs) { var saveEventArgs = eventArgs as SaveEventArgs; record.Event.IsNewItem = saveEventArgs.IsNewItem; } //Extract EventType Specifics switch (eventArgs.GetType().Name) { case "SaveEventArgs": break; default: break; } var events = eventArgs as SaveEventArgs; }
protected Package RunTemplate(Type templateType, IdentifiableObject inputItem, out RenderedItem renderedItem, Template template = null) { renderedItem = CreateTestRenderedItem(inputItem, template); TestEngine testEngine = new TestEngine(renderedItem); Package testPackage = new Package(testEngine); Type inputItemType = inputItem.GetType(); string inputItemName = inputItemType.Name; ContentType inputItemContentType = new ContentType($"tridion/{inputItemType.Name.ToLower()}"); testPackage.PushItem(inputItemName, testPackage.CreateTridionItem(inputItemContentType, inputItem)); ITemplate testTemplate = Activator.CreateInstance(templateType) as ITemplate; Assert.IsNotNull(testTemplate, "testTemplate"); testTemplate.Transform(testEngine, testPackage); return(testPackage); }
public static string FormatIdentifier(this IdentifiableObject identifiableObject) => $"{identifiableObject.GetType().Name} '{identifiableObject.Title}' ({identifiableObject.Id})";
/// <summary> /// Entry point for resolver. /// </summary> /// <param name="item">Item to resolve</param> /// <param name="instruction">Resolve instruction</param> /// <param name="context">Publish context</param> /// <param name="resolvedItems">Final items to resolve</param> public void Resolve(IdentifiableObject item, ResolveInstruction instruction, PublishContext context, Tridion.Collections.ISet <ResolvedItem> resolvedItems) { if (instruction.Purpose != ResolvePurpose.Publish && instruction.Purpose != ResolvePurpose.RePublish || _maxRecurseDepth == 0) { return; } _log.Debug("DXA Custom Resolver started..."); _log.Debug("Loading global app data:"); const string appId = "dxa:CustomResolver"; try { var appData = context.Session.SystemManager.LoadGlobalApplicationData(appId); if (appData != null) { _log.Debug("Found configuration for custom resolver in global app data. Attempting to parse."); string xml = string.Empty; if (appData.TypeId?.StartsWith("XmlElement:") ?? false) { _log.Debug($"Found configuration using XElement appData type."); string @string = Encoding.UTF8.GetString(appData.Data); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(@string); xml = xmlDocument.DocumentElement?.OuterXml; } if (string.IsNullOrEmpty(xml)) { _log.Debug("Assuming string content for xml."); xml = Encoding.Unicode.GetString(appData.Data); } _log.Debug($"xml={xml}"); XElement parsedXml = XElement.Parse(xml); foreach (XElement xe in parsedXml.Elements()) { if (!xe.Name.LocalName.Equals("RecurseDepth")) { continue; } _log.Debug($"Found RecurseDepth value of '{xe.Value}'."); _maxRecurseDepth = int.Parse(xe.Value); break; // only one setting at moment } } else { _log.Debug( $"Custom resolver configuration not found in global app data for '{appId}'. Using default settings."); _maxRecurseDepth = -1; } } catch (Exception e) { _log.Debug( $"Exception occured when reading global app data for application id '{appId}'. Using default settings."); _log.Debug(e.Message); _maxRecurseDepth = -1; } _log.Debug($"Using _maxRecurseDepth={_maxRecurseDepth}"); try { var sourceItem = (RepositoryLocalObject)item; _log.Debug($"Analyzing source item of type: {item.GetType().Name} with id: {item.Id} and title: {item.Title}"); var contextPublication = (Publication)sourceItem.ContextRepository; var filter = new ComponentTemplatesFilter(item.Session) { AllowedOnPage = false, BaseColumns = ListBaseColumns.IdAndTitle }; const string dataPresentationTemplateTitle = "Generate Data Presentation"; var dataPresentationTemplate = contextPublication.GetComponentTemplates(filter).FirstOrDefault( ct => ct.Title == dataPresentationTemplateTitle); if (dataPresentationTemplate == null) { _log.Debug("No 'Generate Data Presentation' component template found. Skipping custom resolver."); return; } var resolved = new HashSet <IdentifiableObject>(); Stopwatch t = new Stopwatch(); t.Start(); HashSet <TcmUri> alreadyResolved = new HashSet <TcmUri>(); foreach (var x in resolvedItems) { alreadyResolved.Add(x.Item.Id); } List <ResolvedItem> resolvedItemsCopy = new List <ResolvedItem>(resolvedItems); foreach (var resolvedItem in resolvedItemsCopy) { foreach (var dataPresentation in ResolveDataPresentations(resolvedItem.Item, dataPresentationTemplate, resolved, 0)) { if (alreadyResolved.Contains(dataPresentation.Item.Id)) { _log.Debug($" > Already resolved item '{dataPresentation.Item.Title}' with id: {dataPresentation.Item.Id}"); continue; } _log.Debug($" > Resolved item '{dataPresentation.Item.Title}' with id: {dataPresentation.Item.Id}"); alreadyResolved.Add(dataPresentation.Item.Id); resolvedItems.Add(dataPresentation); } } t.Stop(); _log.Debug($"DXA Custom Resolver took {t.ElapsedMilliseconds}ms to complete."); } catch (Exception e) { _log.Debug($"Exception occured: {e.Message}"); _log.Debug($"Stacktrace: {e.StackTrace}"); throw; } }
private List <ResolvedItem> ResolveDataPresentations(IdentifiableObject item, ComponentTemplate template, HashSet <IdentifiableObject> resolved, int recurseLevel) { _log.Debug($"Analyzing item for resolving of type: '{item.GetType().Name}' id: '{item.Id}' title: '{item.Title}'"); List <ResolvedItem> toResolve = new List <ResolvedItem>(); if (!ContinueRecursion(recurseLevel)) { _log.Debug($"Reached max recusion level when trying to resolve item {item.Id}, skipping."); return(toResolve); } List <Component> components = new List <Component>(); if (item is Page) { var page = (Page)item; _log.Debug($"Resolving page '{page.Title}' Id={page.Id}"); if (resolved.Contains(page)) { _log.Debug(" * already resolved this page, skipping !"); return(toResolve); } components.AddRange(GatherComponentPresentations(page).Select(cp => cp.Component)); } if (item is Component) { _log.Debug($"Resolving component '{item.Title}' Id={item.Id}"); components.Add(item as Component); } if (components.Count <= 0) { return(toResolve); } var toProcess = new HashSet <Component>(); var depths = new Dictionary <Component, int>(); for (int i = 0; i < components.Count; i++) { // note: avoiding recursive approach here so we can truely do infinite depth without stack overflows var c = components[i]; int depth = recurseLevel; if (depths.ContainsKey(c)) { depth = depths[c]; } if (!ContinueRecursion(depth)) { continue; } if (toProcess.Contains(c)) { continue; } toProcess.Add(c); List <Component> linked = GatherLinkedComponents(c); foreach (var linkedComponent in linked) { if (!ContinueRecursion(depth + 1)) { break; } if (toProcess.Contains(linkedComponent)) { continue; } components.Add(linkedComponent); if (depths.ContainsKey(linkedComponent)) { depths[linkedComponent] = depth + 1; } else { depths.Add(linkedComponent, depth + 1); } } } toResolve.AddRange(toProcess.Select( component => ResolveComponent(component, template, resolved, recurseLevel)).Where(r => r != null)); return(toResolve); }
/// <summary> /// Audits updates to versionless items /// </summary> /// <param name="repositoryObject"><see cref="T:Tridion.ContentManager.ContentManagement.RepositoryLocalObject" /></param> /// <param name="args">The <see cref="SaveEventArgs" /> instance containing the event data.</param> /// <param name="phase"><see cref="T:Tridion.ContentManager.Extensibility.EventPhases" /></param> private void AuditVersionless(IdentifiableObject identifiableObject, SaveEventArgs args, EventPhases phase) { if (phase == EventPhases.Initiated) { try { // Load the original unmodified item XML from the database IdentifiableObject oldIdentifiableObject = identifiableObject.Session.GetObject(identifiableObject.Id); XElement original = XElement.Parse(oldIdentifiableObject.ToXml().OuterXml); XElement updated = XElement.Parse(identifiableObject.ToXml().OuterXml); XElement difference = XMLDelta.Compare(original, updated); if (difference != null) AuditContentEdit("Update", identifiableObject, identifiableObject.GetType().Name, new SqlXml(difference.CreateReader())); else AuditContentEdit("Update", identifiableObject, identifiableObject.GetType().Name, null); } catch (Exception ex) { Logger.Write(ex, "TcmEvents.Audit", LoggingCategory.General, TraceEventType.Error); } } }