private static void DetermineCategoryChanges( CategoryGroup categoryGroup, string originalName, string updatedName, ProfileChangeResult result) { // Categories are stored with case insensitive keys to avoid duplicates // So we don't care if just the case has changed for the category link if (HasStringChanged(originalName, updatedName, StringComparison.OrdinalIgnoreCase)) { if (string.IsNullOrWhiteSpace(originalName) == false) { // There was previous a gender assigned result.AddChange(categoryGroup, originalName, CategoryLinkChangeType.Remove); result.ProfileChanged = true; } if (string.IsNullOrWhiteSpace(updatedName) == false) { // There is a new gender assigned result.AddChange(categoryGroup, updatedName, CategoryLinkChangeType.Add); result.ProfileChanged = true; } } }
private static void DetermineCategoryChanges(Profile original, UpdatableProfile updated, bool findAllCategoryChanges, ProfileChangeResult result) { // Find the category changes DetermineCategoryChanges(CategoryGroup.Gender, original.Gender, updated.Gender, result); if (findAllCategoryChanges == false && result.ProfileChanged) { // We only need to find a single change which we have return; } // Check for changes to languages DetermineCategoryChanges(CategoryGroup.Language, original.Languages, updated.Languages, findAllCategoryChanges, result); if (findAllCategoryChanges == false && result.ProfileChanged) { // We only need to find a single change which we have return; } // Check for changes to skills var originalSkillNames = original.Skills.Select(x => x.Name).ToList(); var updatedSkillNames = updated.Skills.Select(x => x.Name).ToList(); DetermineCategoryChanges(CategoryGroup.Skill, originalSkillNames, updatedSkillNames, findAllCategoryChanges, result); }
public ProfileChangeResult RemoveAllCategoryLinks(UpdatableProfile profile) { Ensure.Any.IsNotNull(profile, nameof(profile)); var result = new ProfileChangeResult(); DetermineAllCategoryRemovalChanges(profile, result); return(result); }
public async Task Execute(Profile profile, ProfileChangeResult changes, CancellationToken cancellationToken) { Ensure.Any.IsNotNull(profile, nameof(profile)); Ensure.Any.IsNotNull(changes, nameof(changes)); if (changes.CategoryChanges.Count > 0) { await UpdateCategories(profile, changes, cancellationToken).ConfigureAwait(false); } if (changes.ProfileChanged) { await UpdateProfile(profile, cancellationToken).ConfigureAwait(false); } }
private static void DetermineAllCategoryAddChanges(UpdatableProfile profile, ProfileChangeResult result) { // Remove gender link DetermineCategoryChanges(CategoryGroup.Gender, null, profile.Gender, result); // Check for changes to languages var emptyCategoryNames = new List <string>(); // Remove all language links DetermineCategoryChanges(CategoryGroup.Language, emptyCategoryNames, profile.Languages, true, result); var skillNames = profile.Skills.Select(x => x.Name).ToList(); // Remove all skill links DetermineCategoryChanges(CategoryGroup.Skill, emptyCategoryNames, skillNames, true, result); }
private static void DetermineCategoryChanges(CategoryGroup categoryGroup, ICollection <string> originalNames, ICollection <string> updatedNames, bool findAllCategoryChanges, ProfileChangeResult result) { foreach (var originalName in originalNames) { var matchingUpdatedName = updatedNames.FirstOrDefault(x => x.Equals(originalName, StringComparison.OrdinalIgnoreCase)); if (matchingUpdatedName == null) { // This category has been removed from profile result.AddChange(categoryGroup, originalName, CategoryLinkChangeType.Remove); result.ProfileChanged = true; } if (findAllCategoryChanges == false && result.ProfileChanged) { // We only need to find a single change which we have return; } } foreach (var updatedName in updatedNames) { var matchingOriginalName = originalNames.FirstOrDefault(x => x.Equals(updatedName, StringComparison.OrdinalIgnoreCase)); if (matchingOriginalName == null) { // This category has been added to the profile result.AddChange(categoryGroup, updatedName, CategoryLinkChangeType.Add); result.ProfileChanged = true; } if (findAllCategoryChanges == false && result.ProfileChanged) { // We only need to find a single change which we have return; } } }
public ProfileChangeResult CalculateChanges(Profile original, UpdatableProfile updated) { Ensure.Any.IsNotNull(original, nameof(original)); Ensure.Any.IsNotNull(updated, nameof(updated)); var result = new ProfileChangeResult(); var canUpdateCategoryLinks = true; if (original.Status == ProfileStatus.Hidden && updated.Status == ProfileStatus.Hidden) { // We don't calculate any changes to category links for a hidden profiles that are still hidden // If we do look for category links to determine if the profile should be saved, we can exit once at least one is found canUpdateCategoryLinks = false; } else if (original.BannedAt != null) { // We don't calculate any changes to category links for a banned profile // If we do look for category links to determine if the profile should be saved, we can exit once at least one is found canUpdateCategoryLinks = false; } if (original.Status != ProfileStatus.Hidden && updated.Status == ProfileStatus.Hidden) { // The profile is being hidden // Remove all the existing category links // We will remove all the links from the original profile // This is because if there are any changes from the original profile to the updated profile, // they aren't stored yet in the links so we don't care DetermineAllCategoryRemovalChanges(original, result); } else if (original.Status == ProfileStatus.Hidden && updated.Status != ProfileStatus.Hidden) { // The profile is being displayed after being hidden // We need to add all the links to the updated profile DetermineAllCategoryAddChanges(updated, result); } else { // Find the category changes between the original and updated profiles DetermineCategoryChanges(original, updated, canUpdateCategoryLinks, result); } if (result.ProfileChanged == false) { result.ProfileChanged = HasProfileChanged(original, updated); } if (result.ProfileChanged == false) { // The profile properties have not changed // We haven't checked for category items added or removed yet, but we also need to check // if any skills have been changed // Search for changes to skill metadata result.ProfileChanged = HaveSkillsChanged(original.Skills, updated.Skills); } if (canUpdateCategoryLinks == false) { // We may have calculated category link changes in order to figure out if the profile should be saved // but we are not going make any category link changes so we need to clear them out result.CategoryChanges.Clear(); } return(result); }
private async Task UpdateCategories( Profile profile, ProfileChangeResult changes, CancellationToken cancellationToken) { var cacheItemsToRemove = new List <ProfileFilter>(); // Get the current categories var categories = (await _categoryStore.GetAllCategories(cancellationToken).ConfigureAwait(false)).FastToList(); var categoryTasks = new List <Task>(); // Write all category link changes foreach (var categoryChange in changes.CategoryChanges) { // Get the category var category = categories.FirstOrDefault( x => x.Group == categoryChange.CategoryGroup && x.Name.Equals( categoryChange.CategoryName, StringComparison.OrdinalIgnoreCase)); if (category == null) { // We haven't seen this category before category = new Category { Group = categoryChange.CategoryGroup, LinkCount = 0, Name = categoryChange.CategoryName, Reviewed = false, Visible = false }; // Trigger a notification that a new category is being added to the system var newCategoryTriggerTask = _eventTrigger.NewCategory(category, cancellationToken); categoryTasks.Add(newCategoryTriggerTask); categories.Add(category); } if (categoryChange.ChangeType == CategoryLinkChangeType.Add) { // This is a new link between the profile and the category category.LinkCount++; } else { // We are removing the link between the profile and the category category.LinkCount--; } var change = new CategoryLinkChange { ChangeType = categoryChange.ChangeType, ProfileId = profile.Id }; // Store the link update var categoryLinkTask = _linkStore.StoreCategoryLink( category.Group, category.Name, change, cancellationToken); categoryTasks.Add(categoryLinkTask); var filter = new ProfileFilter { CategoryGroup = category.Group, CategoryName = category.Name }; cacheItemsToRemove.Add(filter); // Update the category data var categoryTask = _categoryStore.StoreCategory(category, cancellationToken); categoryTasks.Add(categoryTask); } // Run all the category task changes together await Task.WhenAll(categoryTasks).ConfigureAwait(false); UpdateCacheStore(categories, cacheItemsToRemove); }