First step at simplifying Tags implementation

--HG--
branch : dev
rename : src/Orchard.Web/Modules/Orchard.Tags/Models/Tag.cs => src/Orchard.Web/Modules/Orchard.Tags/Models/TagRecord.cs
This commit is contained in:
Renaud Paquay
2010-11-25 09:26:44 -08:00
parent a7a6067497
commit a32765d653
14 changed files with 100 additions and 97 deletions

View File

@@ -25,7 +25,7 @@ namespace Orchard.Tags.Controllers {
public Localizer T { get; set; } public Localizer T { get; set; }
public ActionResult Index() { public ActionResult Index() {
IEnumerable<Tag> tags = _tagService.GetTags(); IEnumerable<TagRecord> tags = _tagService.GetTags();
var entries = tags.Select(CreateTagEntry).ToList(); var entries = tags.Select(CreateTagEntry).ToList();
var model = new TagsAdminIndexViewModel { Tags = entries }; var model = new TagsAdminIndexViewModel { Tags = entries };
return View(model); return View(model);
@@ -50,7 +50,7 @@ namespace Orchard.Tags.Controllers {
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
foreach (TagEntry entry in checkedEntries) { foreach (TagEntry entry in checkedEntries) {
_tagService.DeleteTag(entry.Tag.Id); _tagService.DeleteTag(entry.TagRecord.Id);
} }
break; break;
@@ -80,15 +80,15 @@ namespace Orchard.Tags.Controllers {
} }
public ActionResult Edit(int id) { public ActionResult Edit(int id) {
Tag tag = _tagService.GetTag(id); TagRecord tagRecord = _tagService.GetTag(id);
if(tag == null) { if(tagRecord == null) {
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
var viewModel = new TagsAdminEditViewModel { var viewModel = new TagsAdminEditViewModel {
Id = tag.Id, Id = tagRecord.Id,
TagName = tag.TagName, TagName = tagRecord.TagName,
}; };
ViewData["ContentItems"] = _tagService.GetTaggedContentItems(id).ToList(); ViewData["ContentItems"] = _tagService.GetTaggedContentItems(id).ToList();
@@ -116,9 +116,9 @@ namespace Orchard.Tags.Controllers {
if (!Services.Authorizer.Authorize(Permissions.ManageTags, T("Couldn't remove tag"))) if (!Services.Authorizer.Authorize(Permissions.ManageTags, T("Couldn't remove tag")))
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
Tag tag = _tagService.GetTag(id); TagRecord tagRecord = _tagService.GetTag(id);
if (tag == null) if (tagRecord == null)
return new HttpNotFoundResult(); return new HttpNotFoundResult();
_tagService.DeleteTag(id); _tagService.DeleteTag(id);
@@ -129,9 +129,9 @@ namespace Orchard.Tags.Controllers {
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
private static TagEntry CreateTagEntry(Tag tag) { private static TagEntry CreateTagEntry(TagRecord tagRecord) {
return new TagEntry { return new TagEntry {
Tag = tag, TagRecord = tagRecord,
IsChecked = false, IsChecked = false,
}; };
} }

View File

@@ -50,7 +50,7 @@ namespace Orchard.Tags.Drivers {
var tagNames = TagHelpers.ParseCommaSeparatedTagNames(model.Tags); var tagNames = TagHelpers.ParseCommaSeparatedTagNames(model.Tags);
if (part.ContentItem.Id != 0) { if (part.ContentItem.Id != 0) {
_tagService.UpdateTagsForContentItem(part.ContentItem.Id, tagNames); _tagService.UpdateTagsForContentItem(part.ContentItem, tagNames);
} }
return ContentShape("Parts_Tags_Edit", return ContentShape("Parts_Tags_Edit",

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Orchard.ContentManagement; using Orchard.ContentManagement;
@@ -10,20 +9,13 @@ using Orchard.Tags.Models;
namespace Orchard.Tags.Handlers { namespace Orchard.Tags.Handlers {
[UsedImplicitly] [UsedImplicitly]
public class TagsPartHandler : ContentHandler { public class TagsPartHandler : ContentHandler {
public TagsPartHandler(IRepository<Tag> tagsRepository, IRepository<TagsContentItems> tagsContentItemsRepository) { public TagsPartHandler(IRepository<TagRecord> tagsRepository, IRepository<TagsContentItems> tagsContentItemsRepository) {
OnLoading<TagsPart>((context, tags) => { OnLoading<TagsPart>((context, tags) => {
// provide names of all tags on demand
tags._allTags.Loader(list => tagsRepository.Table.ToList());
// populate list of attached tags on demand // populate list of attached tags on demand
tags._currentTags.Loader(list => { tags._currentTags.Loader(list => {
var tagsContentItems = tagsContentItemsRepository.Fetch(x => x.ContentItemId == context.ContentItem.Id); foreach(var tag in tagsContentItemsRepository.Fetch(x => x.ContentItem == context.ContentItem.Record))
foreach (var tagContentItem in tagsContentItems) { list.Add(tag.Tag);
var tag = tagsRepository.Get(tagContentItem.TagId);
list.Add(tag);
}
return list; return list;
}); });
@@ -32,17 +24,17 @@ namespace Orchard.Tags.Handlers {
OnRemoved<TagsPart>((context, tags) => { OnRemoved<TagsPart>((context, tags) => {
tagsContentItemsRepository.Flush(); tagsContentItemsRepository.Flush();
TagsPart tagsPart = context.ContentItem.As<TagsPart>(); var tagsPart = context.ContentItem.As<TagsPart>();
// delete orphan tags (for each tag, if there is no other contentItem than the one being deleted, it's an orphan) // delete orphan tags (for each tag, if there is no other contentItem than the one being deleted, it's an orphan)
foreach ( var tag in tagsPart.CurrentTags ) { foreach ( var tag in tagsPart.CurrentTags ) {
if ( tagsContentItemsRepository.Fetch(x => x.ContentItemId != context.ContentItem.Id).Count() == 0 ) { if ( tagsContentItemsRepository.Fetch(x => x.ContentItem != context.ContentItem.Record).Count() == 0 ) {
tagsRepository.Delete(tag); tagsRepository.Delete(tag);
} }
} }
// delete tag links with this contentItem (tagsContentItems) // delete tag links with this contentItem (tagsContentItems)
foreach ( var tagsContentItem in tagsContentItemsRepository.Fetch(x => x.ContentItemId == context.ContentItem.Id) ) { foreach ( var tagsContentItem in tagsContentItemsRepository.Fetch(x => x.ContentItem == context.ContentItem.Record) ) {
tagsContentItemsRepository.Delete(tagsContentItem); tagsContentItemsRepository.Delete(tagsContentItem);
} }

View File

@@ -6,7 +6,7 @@ namespace Orchard.Tags {
public class TagsDataMigration : DataMigrationImpl { public class TagsDataMigration : DataMigrationImpl {
public int Create() { public int Create() {
SchemaBuilder.CreateTable("Tag", SchemaBuilder.CreateTable("TagRecord",
table => table table => table
.Column<int>("Id", column => column.PrimaryKey().Identity()) .Column<int>("Id", column => column.PrimaryKey().Identity())
.Column<string>("TagName") .Column<string>("TagName")

View File

@@ -1,5 +1,5 @@
namespace Orchard.Tags.Models { namespace Orchard.Tags.Models {
public class Tag { public class TagRecord {
public virtual int Id { get; set; } public virtual int Id { get; set; }
public virtual string TagName { get; set; } public virtual string TagName { get; set; }
} }

View File

@@ -1,7 +1,9 @@
using Orchard.ContentManagement.Records;
namespace Orchard.Tags.Models { namespace Orchard.Tags.Models {
public class TagsContentItems { public class TagsContentItems {
public virtual int Id { get; set; } public virtual int Id { get; set; }
public virtual int TagId { get; set; } public virtual TagRecord Tag { get; set; }
public virtual int ContentItemId { get; set; } public virtual ContentItemRecord ContentItem { get; set; }
} }
} }

View File

@@ -3,16 +3,13 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Utilities; using Orchard.ContentManagement.Utilities;
namespace Orchard.Tags.Models { namespace Orchard.Tags.Models {
public class TagsPart : ContentPart { public class TagsPart : ContentPart<TagsPartRecord> {
public TagsPart() { public TagsPart() {
AllTags = new List<Tag>(); CurrentTags = new List<TagRecord>();
CurrentTags = new List<Tag>();
} }
public readonly LazyField<IList<Tag>> _allTags = new LazyField<IList<Tag>>(); public readonly LazyField<IList<TagRecord>> _currentTags = new LazyField<IList<TagRecord>>();
public readonly LazyField<IList<Tag>> _currentTags = new LazyField<IList<Tag>>();
public IList<Tag> AllTags { get { return _allTags.Value; } set { _allTags.Value = value; } } public IList<TagRecord> CurrentTags { get { return _currentTags.Value; } set { _currentTags.Value = value; } }
public IList<Tag> CurrentTags { get { return _currentTags.Value; } set { _currentTags.Value = value; } }
} }
} }

View File

@@ -0,0 +1,6 @@
using Orchard.ContentManagement.Records;
namespace Orchard.Tags.Models {
public class TagsPartRecord : ContentPartRecord {
}
}

View File

@@ -55,6 +55,7 @@
<Compile Include="Controllers\AdminController.cs" /> <Compile Include="Controllers\AdminController.cs" />
<Compile Include="Migrations.cs" /> <Compile Include="Migrations.cs" />
<Compile Include="Models\TagsContentItems.cs" /> <Compile Include="Models\TagsContentItems.cs" />
<Compile Include="Models\TagsPartRecord.cs" />
<Compile Include="ResourceManifest.cs" /> <Compile Include="ResourceManifest.cs" />
<Compile Include="Services\ITagService.cs" /> <Compile Include="Services\ITagService.cs" />
<Compile Include="Services\XmlRpcHandler.cs" /> <Compile Include="Services\XmlRpcHandler.cs" />
@@ -63,7 +64,7 @@
<Compile Include="Drivers\TagsPartDriver.cs" /> <Compile Include="Drivers\TagsPartDriver.cs" />
<Compile Include="Helpers\TagHelpers.cs" /> <Compile Include="Helpers\TagHelpers.cs" />
<Compile Include="Models\TagsPart.cs" /> <Compile Include="Models\TagsPart.cs" />
<Compile Include="Models\Tag.cs" /> <Compile Include="Models\TagRecord.cs" />
<Compile Include="Handlers\TagsPartHandler.cs" /> <Compile Include="Handlers\TagsPartHandler.cs" />
<Compile Include="Permissions.cs" /> <Compile Include="Permissions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />

View File

@@ -4,14 +4,17 @@ using Orchard.Tags.Models;
namespace Orchard.Tags.Services { namespace Orchard.Tags.Services {
public interface ITagService : IDependency { public interface ITagService : IDependency {
IEnumerable<Tag> GetTags(); IEnumerable<TagRecord> GetTags();
Tag GetTag(int id); TagRecord GetTag(int tagId);
Tag GetTagByName(string tagName); TagRecord GetTagByName(string tagName);
IEnumerable<IContent> GetTaggedContentItems(int tagId);
void CreateTag(string tagName); void CreateTag(string tagName);
void DeleteTag(int id);
void UpdateTag(int id, string tagName); void DeleteTag(int tagId);
IEnumerable<IContent> GetTaggedContentItems(int id);
void TagContentItem(int contentItemId, string tagName); void UpdateTag(int tagId, string tagName);
void UpdateTagsForContentItem(int contentItemId, IEnumerable<string> tagNamesForContentItem);
void UpdateTagsForContentItem(ContentItem contentItem, IEnumerable<string> tagNamesForContentItem);
} }
} }

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Orchard.ContentManagement.Records;
using Orchard.Data; using Orchard.Data;
using Orchard.Localization; using Orchard.Localization;
using Orchard.Logging; using Orchard.Logging;
@@ -13,13 +14,13 @@ using Orchard.UI.Notify;
namespace Orchard.Tags.Services { namespace Orchard.Tags.Services {
[UsedImplicitly] [UsedImplicitly]
public class TagService : ITagService { public class TagService : ITagService {
private readonly IRepository<Tag> _tagRepository; private readonly IRepository<TagRecord> _tagRepository;
private readonly IRepository<TagsContentItems> _tagsContentItemsRepository; private readonly IRepository<TagsContentItems> _tagsContentItemsRepository;
private readonly INotifier _notifier; private readonly INotifier _notifier;
private readonly IAuthorizationService _authorizationService; private readonly IAuthorizationService _authorizationService;
private readonly IOrchardServices _orchardServices; private readonly IOrchardServices _orchardServices;
public TagService(IRepository<Tag> tagRepository, public TagService(IRepository<TagRecord> tagRepository,
IRepository<TagsContentItems> tagsContentItemsRepository, IRepository<TagsContentItems> tagsContentItemsRepository,
INotifier notifier, INotifier notifier,
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
@@ -36,15 +37,15 @@ namespace Orchard.Tags.Services {
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
public Localizer T { get; set; } public Localizer T { get; set; }
public IEnumerable<Tag> GetTags() { public IEnumerable<TagRecord> GetTags() {
return _tagRepository.Table.ToList(); return _tagRepository.Table.ToList();
} }
public Tag GetTag(int id) { public TagRecord GetTag(int tagId) {
return _tagRepository.Get(x => x.Id == id); return _tagRepository.Get(x => x.Id == tagId);
} }
public Tag GetTagByName(string tagName) { public TagRecord GetTagByName(string tagName) {
return _tagRepository.Get(x => x.TagName == tagName); return _tagRepository.Get(x => x.TagName == tagName);
} }
@@ -52,97 +53,98 @@ namespace Orchard.Tags.Services {
if (_tagRepository.Get(x => x.TagName == tagName) == null) { if (_tagRepository.Get(x => x.TagName == tagName) == null) {
_authorizationService.CheckAccess(Permissions.CreateTag, _orchardServices.WorkContext.CurrentUser, null); _authorizationService.CheckAccess(Permissions.CreateTag, _orchardServices.WorkContext.CurrentUser, null);
Tag tag = new Tag { TagName = tagName }; TagRecord tagRecord = new TagRecord { TagName = tagName };
_tagRepository.Create(tag); _tagRepository.Create(tagRecord);
} }
else { else {
_notifier.Warning(T("The tag {0} already exists", tagName)); _notifier.Warning(T("The tag {0} already exists", tagName));
} }
} }
public void DeleteTag(int id) { public void DeleteTag(int tagId) {
_tagRepository.Delete(GetTag(id)); _tagRepository.Delete(GetTag(tagId));
IEnumerable<TagsContentItems> tagsContentItems = _tagsContentItemsRepository.Fetch(x => x.TagId == id); IEnumerable<TagsContentItems> tagsContentItems = _tagsContentItemsRepository.Fetch(x => x.Tag.Id == tagId);
foreach (var tagContentItem in tagsContentItems) { foreach (var tagContentItem in tagsContentItems) {
_tagsContentItemsRepository.Delete(tagContentItem); _tagsContentItemsRepository.Delete(tagContentItem);
} }
} }
public void UpdateTag(int id, string tagName) { public void UpdateTag(int tagId, string tagName) {
if ( String.IsNullOrEmpty(tagName) ) { if (String.IsNullOrEmpty(tagName)) {
_notifier.Warning(T("Couldn't rename tag: name was empty")); _notifier.Warning(T("Couldn't rename tag: name was empty"));
return; return;
} }
Tag tag = GetTagByName(tagName); var tagRecord = GetTagByName(tagName);
if(tag != null) {
// new tag name already existing => merge // new tag name already existing => merge
IEnumerable<TagsContentItems> tagsContentItems = _tagsContentItemsRepository.Fetch(x => x.TagId == id); if (tagRecord != null) {
var tagsContentItems = _tagsContentItemsRepository.Fetch(x => x.Tag.Id == tagId);
// get contentItems already tagged with the existing one // get contentItems already tagged with the existing one
var taggedContentItems = GetTaggedContentItems(tag.Id); var taggedContentItems = GetTaggedContentItems(tagRecord.Id);
foreach ( var tagContentItem in tagsContentItems ) { foreach (var tagContentItem in tagsContentItems) {
var tagContentItemId = tagContentItem.ContentItemId; if (!taggedContentItems.Any(c => c.ContentItem.Record == tagContentItem.ContentItem)) {
if ( !taggedContentItems.Any(c => c.ContentItem.Id == tagContentItemId) ) { TagContentItem(tagContentItem.ContentItem, tagName);
TagContentItem(tagContentItem.ContentItemId, tagName);
} }
_tagsContentItemsRepository.Delete(tagContentItem); _tagsContentItemsRepository.Delete(tagContentItem);
} }
_tagRepository.Delete(GetTag(id)); _tagRepository.Delete(GetTag(tagId));
} return;
else {
tag = _tagRepository.Get(id);
tag.TagName = tagName;
}
} }
public IEnumerable<IContent> GetTaggedContentItems(int id) { // Create new tag
tagRecord = _tagRepository.Get(tagId);
tagRecord.TagName = tagName;
}
public IEnumerable<IContent> GetTaggedContentItems(int tagId) {
return _tagsContentItemsRepository return _tagsContentItemsRepository
.Fetch(x => x.TagId == id) .Fetch(x => x.Tag.Id == tagId)
.Select(t =>_orchardServices.ContentManager.Get(t.ContentItemId)) .Select(t => _orchardServices.ContentManager.Get(t.ContentItem.Id))
.Where(c => c!= null); .Where(c => c != null);
} }
public void TagContentItem(int contentItemId, string tagName) { private void TagContentItem(ContentItemRecord contentItem, string tagName) {
Tag tag = GetTagByName(tagName); var tagRecord = GetTagByName(tagName);
TagsContentItems tagsContentItems = new TagsContentItems { ContentItemId = contentItemId, TagId = tag.Id }; var tagsContentItems = new TagsContentItems { ContentItem = contentItem, Tag = tagRecord };
_tagsContentItemsRepository.Create(tagsContentItems); _tagsContentItemsRepository.Create(tagsContentItems);
} }
public void UpdateTagsForContentItem(int contentItemId, IEnumerable<string> tagNamesForContentItem) { public void UpdateTagsForContentItem(ContentItem contentItem, IEnumerable<string> tagNamesForContentItem) {
List<int> tags = new List<int>(); var tags = new List<TagRecord>();
foreach (var tagName in tagNamesForContentItem) { foreach (var tagName in tagNamesForContentItem) {
Tag tag = GetTagByName(tagName); TagRecord tagRecord = GetTagByName(tagName);
if (tag == null) { if (tagRecord == null) {
CreateTag(tagName); CreateTag(tagName);
tag = GetTagByName(tagName); tagRecord = GetTagByName(tagName);
} }
tags.Add(tag.Id); tags.Add(tagRecord);
} }
ModifyTagsForContentItem(contentItemId, tags); ModifyTagsForContentItem(contentItem, tags);
} }
private void ModifyTagsForContentItem(int contentItemId, IEnumerable<int> tagsForContentItem) { private void ModifyTagsForContentItem(ContentItem contentItem, IEnumerable<TagRecord> tagsForContentItem) {
List<int> newTagsForContentItem = new List<int>(tagsForContentItem); var newTagsForContentItem = new List<TagRecord>(tagsForContentItem);
IEnumerable<TagsContentItems> currentTagsForContentItem = _tagsContentItemsRepository.Fetch(x => x.ContentItemId == contentItemId); var currentTagsForContentItem = _tagsContentItemsRepository.Fetch(x => x.ContentItem == contentItem.Record);
foreach (var tagContentItem in currentTagsForContentItem) { foreach (var tagContentItem in currentTagsForContentItem) {
if (!newTagsForContentItem.Contains(tagContentItem.TagId)) { if (!newTagsForContentItem.Contains(tagContentItem.Tag)) {
_authorizationService.CheckAccess(Permissions.ApplyTag, _orchardServices.WorkContext.CurrentUser, null); _authorizationService.CheckAccess(Permissions.ApplyTag, _orchardServices.WorkContext.CurrentUser, null);
_tagsContentItemsRepository.Delete(tagContentItem); _tagsContentItemsRepository.Delete(tagContentItem);
} }
else { else {
newTagsForContentItem.Remove(tagContentItem.TagId); newTagsForContentItem.Remove(tagContentItem.Tag);
} }
} }
foreach (var newTagForContentItem in newTagsForContentItem) { foreach (var newTagForContentItem in newTagsForContentItem) {
_authorizationService.CheckAccess(Permissions.ApplyTag, _orchardServices.WorkContext.CurrentUser, null); _authorizationService.CheckAccess(Permissions.ApplyTag, _orchardServices.WorkContext.CurrentUser, null);
_tagsContentItemsRepository.Create(new TagsContentItems { ContentItemId = contentItemId, TagId = newTagForContentItem }); _tagsContentItemsRepository.Create(new TagsContentItems { ContentItem = contentItem.Record, Tag = newTagForContentItem });
} }
} }
} }

View File

@@ -158,7 +158,7 @@ namespace Orchard.Tags.Services {
return; return;
_orchardServices.WorkContext.CurrentUser = user; _orchardServices.WorkContext.CurrentUser = user;
_tagService.UpdateTagsForContentItem(id, tags); _tagService.UpdateTagsForContentItem(contentItem, tags);
}); });
if (contentItemId > 0) if (contentItemId > 0)

View File

@@ -8,7 +8,7 @@ namespace Orchard.Tags.ViewModels {
} }
public class TagEntry { public class TagEntry {
public Tag Tag { get; set; } public TagRecord TagRecord { get; set; }
public bool IsChecked { get; set; } public bool IsChecked { get; set; }
} }

View File

@@ -3,6 +3,6 @@ using Orchard.Tags.Models;
namespace Orchard.Tags.ViewModels { namespace Orchard.Tags.ViewModels {
public class TagsIndexViewModel { public class TagsIndexViewModel {
public IList<Tag> Tags { get; set; } public IList<TagRecord> Tags { get; set; }
} }
} }