Esempio n. 1
0
        public TagUsageForApiContract[] AddTags <TEntry, TTag>(int entryId, TagBaseContract[] tags,
                                                               bool onlyAdd,
                                                               IRepository <User> repository,
                                                               IEntryLinkFactory entryLinkFactory,
                                                               IEnumTranslations enumTranslations,
                                                               Func <TEntry, TagManager <TTag> > tagFunc,
                                                               Func <TEntry, IDatabaseContext <TTag>, ITagUsageFactory <TTag> > tagUsageFactoryFactory)
            where TEntry : IEntryWithNames, IEntryWithTags where TTag : TagUsage
        {
            ParamIs.NotNull(() => tags);

            permissionContext.VerifyManageDatabase();

            tags = tags.Where(IsValid).ToArray();

            if (onlyAdd && !tags.Any())
            {
                return(new TagUsageForApiContract[0]);
            }

            return(repository.HandleTransaction(ctx => {
                // Tags are primarily added by Id, secondarily by translated name.
                // First separate given tags for tag IDs and tag names
                var tagIds = tags.Where(HasId).Select(t => t.Id).ToArray();
                var translatedTagNames = tags.Where(t => !HasId(t) && !string.IsNullOrEmpty(t.Name)).Select(t => t.Name).ToArray();

                // Load existing tags by name and ID.
                var tagsFromIds = ctx.Query <Tag>().Where(t => tagIds.Contains(t.Id)).ToArray();

                var tagsFromNames = ctx.Query <Tag>().WhereHasName(translatedTagNames).ToArray();

                // Figure out tags that don't exist yet (no ID and no matching name).
                var newTagNames = translatedTagNames.Except(tagsFromNames.SelectMany(t => t.Names.AllValues), StringComparer.InvariantCultureIgnoreCase).ToArray();

                var user = ctx.OfType <User>().GetLoggedUser(permissionContext);
                var tagFactory = new TagFactoryRepository(ctx.OfType <Tag>(), new AgentLoginData(user));
                var newTags = newTagNames.Select(t => tagFactory.CreateTag(t)).ToArray();

                // Get the final list of tag names with translations
                var appliedTags = tagsFromNames.Concat(tagsFromIds).Concat(newTags).Distinct().ToArray();

                var entry = ctx.OfType <TEntry>().Load(entryId);
                var tagUsageFactory = tagUsageFactoryFactory(entry, ctx.OfType <TTag>());

                var tagNames = appliedTags.Select(t => t.DefaultName);
                ctx.AuditLogger.AuditLog(string.Format("tagging {0} with {1}",
                                                       entryLinkFactory.CreateEntryLink(entry), string.Join(", ", tagNames)), user);

                var addedTags = appliedTags.Except(entry.Tags.Tags).ToArray();
                new FollowedTagNotifier().SendNotifications(ctx, entry, addedTags, new[] { user.Id }, entryLinkFactory, enumTranslations);

                var updatedTags = tagFunc(entry).SyncVotes(user, appliedTags, tagUsageFactory, onlyAdd: onlyAdd);
                var tagCtx = ctx.OfType <Tag>();

                foreach (var tag in updatedTags)
                {
                    tagCtx.Update(tag);
                }

                RecomputeTagUsagesCounts(tagCtx, updatedTags);

                ctx.AuditLogger.SysLog("finished tagging");

                return tagFunc(entry).ActiveUsages.Select(t => new TagUsageForApiContract(t, permissionContext.LanguagePreference)).ToArray();
            }));
        }