/// <summary> /// Called after saving of the specified enumeration of entities has taken place. /// </summary> /// <param name="entities">The entities.</param> /// <param name="state">The state.</param> public void OnAfterSave(IEnumerable <IEntity> entities, IDictionary <string, object> state) { object duplicates; HashSet <long> entitiesToDeleteSet = new HashSet <long>(); // Get any merged duplicates to delete if (state.TryGetValue(ResourceKeyHelper.MergedDuplicatesStateKey, out duplicates)) { var duplicatesAsHashSet = duplicates as HashSet <long>; if (duplicatesAsHashSet != null && duplicatesAsHashSet.Count != 0) { entitiesToDeleteSet.UnionWith(duplicatesAsHashSet.Select(id => EventTargetStateHelper.GetIdFromTemporaryId(state, id))); } } Dictionary <long, ResourceKeyDataHash> dataHashesToDelete = ResourceKeyHelper.GetResourceKeyDataHashToDeleteState(state); // Get any datahashes to delete if (dataHashesToDelete != null && dataHashesToDelete.Count != 0) { entitiesToDeleteSet.UnionWith(dataHashesToDelete.Keys); } if (entitiesToDeleteSet.Count != 0) { Entity.Delete(entitiesToDeleteSet); } object movedEntitiesObject; if (state.TryGetValue("movedEntities", out movedEntitiesObject)) { Dictionary <long, ISet <long> > movedEntities = movedEntitiesObject as Dictionary <long, ISet <long> >; if (movedEntities != null) { using (DatabaseContext context = DatabaseContext.GetContext( )) { foreach (KeyValuePair <long, ISet <long> > pair in movedEntities) { using (IDbCommand command = context.CreateCommand("spPostEntityMove", CommandType.StoredProcedure)) { command.AddIdListParameter("@entityIds", pair.Value); command.AddParameter("@tenantId", DbType.Int64, RequestContext.TenantId); command.AddParameter("@solutionId", DbType.Int64, pair.Key); command.ExecuteNonQuery( ); } } } } } // Save the resource key data hashes for any resources at the reverse end // of any key relationships. ResourceKeyHelper.SaveResourceKeyDataHashesForReverseRelationships(entities, state); }
/// <summary> /// Called after saving of the specified enumeration of entities has taken place. /// </summary> /// <param name="entities">The entities.</param> /// <param name="state">The state passed between the before save and after save callbacks.</param> public void OnAfterSave(IEnumerable <IEntity> entities, IDictionary <string, object> state) { object entry; IDictionary <long, EntityChanges> modifiedRelatedEntities; // Filter out certain entity changes (namely modifying softwarePlatformOpenIdProvider, which keeps invalidating our caches) IList <IEntity> entityList = FilterEntityChangeList(entities); if (entityList.Count == 0) { return; } // Get the SaveGraph, for mappings between TempIDs and real IDs. SaveGraph saveGraph = EventTargetStateHelper.GetSaveGraph(state); IList <EntityRef> relationshipTypes = null; IList <long> fieldTypes = null; foreach (ICacheInvalidator cacheInvalidator in Invalidators.ToList( )) { modifiedRelatedEntities = null; if (state.TryGetValue(cacheInvalidator.Name, out entry)) { modifiedRelatedEntities = entry as IDictionary <long, EntityChanges>; } Func <long, EntityChanges> entityChangeGetter = CreateEntityChangesCallback(saveGraph, modifiedRelatedEntities); cacheInvalidator.OnEntityChange(entityList, InvalidationCause.Save, entityChangeGetter); if (modifiedRelatedEntities != null) { if (relationshipTypes == null) { relationshipTypes = modifiedRelatedEntities.Where(kvp => kvp.Value != null) .SelectMany(kvp => kvp.Value.RelationshipTypesToEntities.Select(rte => rte.RelationshipType)) .ToList( ); } cacheInvalidator.OnRelationshipChange(relationshipTypes); if (fieldTypes == null) { fieldTypes = modifiedRelatedEntities.Where(kvp => kvp.Value != null) .SelectMany(kvp => kvp.Value.FieldTypes) .ToList( ); } cacheInvalidator.OnFieldChange(fieldTypes); } // Invalidate if this is a field or relationship InvalidateFieldOrRelationshipIfEntityIsFieldOrRelationship(entityList, cacheInvalidator); } }
/// <summary> /// Ensures the form is the default form for the type. /// </summary> /// <param name="form">The form.</param> /// <param name="state">The state.</param> private void EnsureIsDefaultFormForType(CustomEditForm form, IDictionary <string, object> state) { IEntityFieldValues changedFields; IDictionary <long, IChangeTracker <IMutableIdKey> > changedFwdRelationships; IDictionary <long, IChangeTracker <IMutableIdKey> > changedRevRelationships; form.GetChanges(out changedFields, out changedFwdRelationships, out changedRevRelationships, false, false); if (changedRevRelationships == null || changedRevRelationships.Count == 0) { // No changes return; } var saveGraph = EventTargetStateHelper.GetSaveGraph(state); ResourceEventTarget.EnsureIsOnlyRelationship(EntityType.DefaultEditForm_Field.Id, true, form, changedRevRelationships, saveGraph); }
/// <summary> /// Called after saving of the specified enumeration of entities has taken place. /// </summary> /// <param name="entities">The entities.</param> /// <param name="state">The state passed between the before save and after save callbacks.</param> public void OnAfterSave(IEnumerable <IEntity> entities, IDictionary <string, object> state) { foreach (long entityId in entities.Select(e => e.Id)) { _auditLogEventTarget.WriteSaveAuditLogEntries(true, entityId, state); } var newTenantTempIds = (List <long>)state[NewTenantKey]; Database.DatabaseContext.GetContext().AddPostDisposeAction(() => { foreach (var tempId in newTenantTempIds) { var tenantId = EventTargetStateHelper.GetIdFromTemporaryId(state, tempId); TenantHelper.NotifyTenantCreate(tenantId); } }); }
/// <summary> /// Ensures the report is the default report for the type. /// </summary> private void EnsureIsDefaultReportForType(Report report, IDictionary <string, object> state) { IEntityFieldValues changedFields; IDictionary <long, IChangeTracker <IMutableIdKey> > changedFwdRelationships; IDictionary <long, IChangeTracker <IMutableIdKey> > changedRevRelationships; report.GetChanges(out changedFields, out changedFwdRelationships, out changedRevRelationships, false, false); if (changedRevRelationships == null || changedRevRelationships.Count == 0) { // No changes return; } SaveGraph saveGraph = EventTargetStateHelper.GetSaveGraph(state); ResourceEventTarget.EnsureIsOnlyRelationship(EntityType.DefaultPickerReport_Field.Id, true, report, changedRevRelationships, saveGraph); ResourceEventTarget.EnsureIsOnlyRelationship(EntityType.DefaultDisplayReport_Field.Id, true, report, changedRevRelationships, saveGraph); }
/// <summary> /// Processes the new solutions. /// </summary> /// <param name="entities">The entities.</param> /// <param name="state">The state.</param> private static void ProcessNewSolutions(IEnumerable <IEntity> entities, IDictionary <string, object> state) { object newSolutionsObject; if (state.TryGetValue(NewSolutionsKey, out newSolutionsObject)) { var newSolutions = (List <IEntity>)newSolutionsObject; IList <IEntity> enumerable = entities as IList <IEntity> ?? entities.ToList(); foreach (IEntity newSolution in newSolutions) { long temporaryId = EventTargetStateHelper.GetIdFromTemporaryId(state, newSolution.Id); IEntity entity = enumerable.FirstOrDefault(e => e.Id == temporaryId); if (entity != null) { var solution = entity.As <Solution>(); if (solution == null) { continue; } if (solution.IsReadOnly) { solution = solution.AsWritable <Solution>(); } SetInSolutionRelationship(solution); solution.Save(); } } DetermineIfNewTabNeeded(enumerable); state.Remove(NewSolutionsKey); } }
public bool OnBeforeSave(IEnumerable <IEntity> entities, IDictionary <string, object> state) { foreach (Document document in from entity in entities where entity.Is <Document>() select entity.AsWritable <Document>()) { // Populate the document revision DocumentRevision revision = Entity.Create <DocumentRevision>(); bool createNewRevision = false; bool initialRevision = false; if (EntityTemporaryIdAllocator.IsAllocatedId(document.Id)) { // Populate the initial version string for the document revision.VersionComments = @"Initial Version"; revision.Version = @"1.0"; revision.Name = revision.Version; createNewRevision = true; initialRevision = true; } else { DocumentRevision currentRevision = document.CurrentDocumentRevision; if (currentRevision?.FileDataHash != document.FileDataHash) { // Extract the version number and increment it string newRevision = string.Format("{0}.0", Convert.ToInt32(currentRevision.Version.Split('.')[0]) + 1); revision.VersionComments = document.Description; // Need to modify the document entity to include a hidden field for comments ?? revision.Version = newRevision; revision.Name = newRevision; createNewRevision = true; } } if (createNewRevision) { revision.FileExtension = document.FileExtension; revision.ModifiedDate = DateTime.UtcNow; revision.Size = document.Size; // Get the entity that represents the user UserAccount userAccount = Entity.Get <UserAccount>(RequestContext.GetContext().Identity.Id); // Associate the revision to the account revision.RevisionUpdatedBy = userAccount; // Associate the file to this revision revision.FileDataHash = document.FileDataHash; SaveGraph saveGraph = EventTargetStateHelper.GetSaveGraph(state); saveGraph.Entities[revision.Id] = revision; document.CurrentDocumentRevision = revision; // Associate the document to the revision (documentHasDocumentRevision - used for version history listing) document.DocumentHasDocumentRevision.Add(revision); // Associate the last created user to the document if (initialRevision) { document.DocumentCreatedBy = userAccount; } // Associate the last modified user to the document document.DocumentModifiedBy = userAccount; } document.DocumentHasDocumentType = document.DocumentFileType; if (document.InFolder == null) { // Default document dumping ground if not specified document.InFolder = Entity.Get <DocumentFolder>(new EntityRef("core", "documentsDocumentFolder")); } } return(false); }