17 using System.Collections.Generic;
18 using System.Globalization;
20 using System.Security;
22 using erminas.SmartAPI.CMS.Project.ContentClasses;
23 using erminas.SmartAPI.CMS.Project.ContentClasses.Elements;
24 using erminas.SmartAPI.CMS.Project.Folder;
25 using erminas.SmartAPI.CMS.Project.Keywords;
26 using erminas.SmartAPI.CMS.Project.Pages;
27 using erminas.SmartAPI.CMS.Project.Publication;
28 using erminas.SmartAPI.CMS.ServerManagement;
29 using erminas.SmartAPI.Exceptions;
30 using erminas.SmartAPI.Utils;
31 using erminas.SmartAPI.Utils.CachedCollections;
33 namespace erminas.SmartAPI.CMS.Project
45 AdminAndPublisher = 17
50 IIndexedRDList<string, IContentClassFolder> Broken {
get; }
53 internal class ContentClassFolders : NameIndexedRDList<IContentClassFolder>, IContentClassFolders
55 private readonly Project _project;
57 internal ContentClassFolders(Project project,
Caching caching) : base(caching)
60 RetrieveFunc = GetContentClassFolders;
61 Broken =
new NameIndexedRDList<IContentClassFolder>(GetBrokenFolders,
Caching.Enabled);
64 public IIndexedRDList<string, IContentClassFolder> Broken {
get;
private set; }
66 public IProject Project
68 get {
return _project; }
71 public ISession Session
73 get {
return _project.Session; }
76 private List<IContentClassFolder> GetBrokenFolders()
79 @"<TREESEGMENT type=""project.4000"" action=""load"" guid=""4AF89E44535511D4BDAB004005312B7C"" descent=""app"" parentguid=""""/>";
80 var result = Project.ExecuteRQL(TREE);
81 var guids = this.Select(folder => folder.Guid)
83 return (from XmlElement element in result.GetElementsByTagName(
"SEGMENT")
84 let curGuid = element.GetGuid()
85 where !guids.Contains(curGuid)
88 Name = element.GetAttributeValue(
"value"),
93 private List<IContentClassFolder> GetContentClassFolders()
95 const string LIST_CC_FOLDERS_OF_PROJECT =
@"<TEMPLATEGROUPS action=""load"" />";
97 XmlDocument xmlDoc = Session.ExecuteRQLInProjectContext(LIST_CC_FOLDERS_OF_PROJECT, _project.Guid);
98 XmlNodeList xmlNodes = xmlDoc.GetElementsByTagName(
"GROUP");
100 return (from XmlElement curNode in xmlNodes select (
IContentClassFolder)
new ContentClassFolder(_project, curNode)).ToList();
135 IIndexedCachedList<int, IInfoAttribute> InfoAttributes {
get; }
141 IIndexedRDList<string, IUser> OnlineUsers {
get; }
143 bool IsArchivingActive {
get; }
145 bool IsLockedBySystem {
get; }
147 bool IsVersioningActive {
get;
set; }
152 IRDList<IKeyword> Keywords {
get; }
174 IRDList<IPublicationFolder> PublicationFolders {
get; }
179 IRDList<IPublicationPackage> PublicationPackages {
get; }
184 IRDList<IPublicationTarget> PublicationTargets {
get; }
207 void DeleteWithDatabase(
string databaseUser,
string password);
215 XmlDocument ExecuteRQL(
string query,
RqlType type =
RqlType.SessionKeyInIodata);
217 void ClearPageCache();
220 string GetTextContent(Guid textElementGuid,
ILanguageVariant lang,
string typeString);
242 "This was not meant as public API and will be removed in the next major release. Do NOT use it, it probably won't do what you think it does!"
244 Guid SetTextContent(Guid textElementGuid,
ILanguageVariant languageVariant,
string typeString,
string content);
259 internal class Project : PartialRedDotObject, IProject
262 private readonly
IPages _pages;
263 private bool _isLockedBySystem;
265 private IPage _startPage;
266 private IProjectClipboard _clipboard;
268 internal Project(
ISession session, XmlElement xmlElement) : base(session, xmlElement)
270 _contentClasses =
new ContentClasses.ContentClasses(
this);
276 internal Project(ISession session, Guid guid) : base(session, guid)
278 _contentClasses =
new ContentClasses.ContentClasses(
this);
283 internal XmlDocument AllFoldersXmlDocument {
get;
set; }
286 public IProjectGroups AssignedGroups {
get;
private set; }
292 [VersionIsGreaterThanOrEqual(10)]
293 public IProjectClipboard Clipboard
297 VersionVerifier.EnsureVersion(Session);
302 public IIndexedRDList<string, IUser> OnlineUsers {
get;
private set; }
307 public IContentClassFolders ContentClassFolders {
get;
private set; }
311 get {
return _contentClasses; }
314 public IProjectCopyJob CreateCopyJob(
string newProjectName)
316 return new ProjectCopyJob(
this, newProjectName);
319 public IProjectExportJob CreateExportJob(
string targetPath)
321 return new ProjectExportJob(
this, targetPath);
327 public IDatabaseConnections DatabaseConnections {
get;
private set; }
332 public void DeleteWithDatabase(
string databaseUser,
string password)
334 const string DELETE_PROJECT =
335 @"<ADMINISTRATION><PROJECT action=""delete"" guid=""{0}"" deletedb=""{1}"" user=""{2}"" password=""{3}""/></ADMINISTRATION>";
336 Session.ExecuteRQL(DELETE_PROJECT.RQLFormat(
this,
true, databaseUser, password));
346 public XmlDocument ExecuteRQL(
string query,
RqlType type =
RqlType.SessionKeyInIodata)
350 case RqlType.SessionKeyInIodata:
351 return Session.ExecuteRQLInProjectContext(query, Guid);
352 case RqlType.SessionKeyInProject:
353 return Session.ExecuteRQLInProjectContextAndEmbeddedInProjectElement(query, Guid);
355 throw new ArgumentException(
string.Format(
"Unknown query type: {0}", type));
359 public void ClearPageCache()
361 const string CLEAR_PAGE_CACHE =
@"<PBCACHE><CACHE action=""delete""/></PBCACHE>";
362 ExecuteRQL(CLEAR_PAGE_CACHE);
368 public IFolders Folders {
get;
private set; }
371 public string GetTextContent(Guid textElementGuid, ILanguageVariant lang,
string typeString)
373 return Session.GetTextContent(Guid, lang, textElementGuid, typeString);
379 public IIndexedCachedList<int, IInfoAttribute> InfoAttributes {
get;
private set; }
381 public bool IsArchivingActive
385 EnsureInitialization();
386 return XmlElement.GetIntAttributeValue(
"archive")
387 .GetValueOrDefault() == -1;
391 public bool IsLockedBySystem
393 get {
return LazyLoad(ref _isLockedBySystem); }
397 public bool IsVersioningActive
401 EnsureInitialization();
402 return XmlElement.GetIntAttributeValue(
"versioning")
403 .GetValueOrDefault() == -1;
408 const string SET_VERISONING =
@"<ADMINISTRATION><PROJECT action=""save"" guid=""{2}"" versioning=""{3}""/></ADMINISTRATION>";
409 Session.ExecuteRQL(SET_VERISONING.RQLFormat(Session.LogonGuid, Session.CurrentUser,
this, value));
416 public IRDList<IKeyword> Keywords {
get;
private set; }
421 public ILanguageVariants LanguageVariants {
get;
private set; }
428 get {
return LazyLoad(ref _locklevel); }
433 get {
return _pages; }
439 public IProjectVariants ProjectVariants {
get;
private set; }
444 public IRDList<IPublicationFolder> PublicationFolders {
get;
private set; }
449 public IRDList<IPublicationPackage> PublicationPackages {
get;
private set; }
454 public IRDList<IPublicationTarget> PublicationTargets {
get;
private set; }
456 public IRecycleBin RecycleBin {
get;
private set; }
458 public IProject Refreshed()
469 Session.SelectProject(
this);
485 throw new SmartAPIException(Session.ServerLogin,
"Info message for project locking must not be empty");
487 const string SET_LOCKLEVEL =
488 @"<ADMINISTRATION><PROJECT action=""save"" guid=""{0}"" inhibitlevel=""{1}"" lockinfo=""{2}""/></ADMINISTRATION>";
492 SET_LOCKLEVEL.RQLFormat(
496 ? RQL.SESSIONKEY_PLACEHOLDER
497 : SecurityElement.Escape(infoMessage)));
498 var project = (XmlElement) xmlDoc.SelectSingleNode(
"//PROJECT");
499 if (!project.GetAttributeValue(
"inhibitlevel")
500 .Equals(((
int) level).ToString(CultureInfo.InvariantCulture)))
502 throw new SmartAPIException(Session.ServerLogin,
string.Format(
"Could not set project lock level to {0}", level));
507 public Guid SetTextContent(Guid textElementGuid, ILanguageVariant languageVariant,
string typeString,
string content)
509 return Session.SetTextContent(Guid, languageVariant, textElementGuid, typeString, content);
515 public ISyllables Syllables {
get;
private set; }
520 public IProjectUsers Users {
get;
private set; }
522 public IProjectWorkflows Workflows {
get;
private set; }
524 protected override void LoadWholeObject()
529 protected override XmlElement RetrieveWholeObject()
531 if (Session.CurrentUser.ModuleAssignment.IsServerManager)
533 return ((Project) Session.ServerManager.Projects.GetByGuid(Guid)).XmlElement;
535 return ((Project) Session.ServerManager.Projects.ForCurrentUser.GetByGuid(Guid)).XmlElement;
538 private List<IInfoAttribute> GetInfoAttributes()
540 const string LOAD_INFO_ELEMENTS =
@"<TEMPLATE><INFOELEMENTS action=""list""></INFOELEMENTS></TEMPLATE>";
541 XmlDocument xmlDoc = ExecuteRQL(LOAD_INFO_ELEMENTS);
542 var infos = xmlDoc.GetElementsByTagName(
"INFOELEMENTS")[0] as XmlElement;
545 throw new SmartAPIException(Session.ServerLogin,
"Could not load info elements");
548 (from XmlElement info in infos.GetElementsByTagName(
"PAGEINFO") select (
IInfoAttribute) new InfoAttribute(info)).Union(
554 .GetElementsByTagName
565 (from XmlElement info in infos.GetElementsByTagName("SESSIONOBJECT")
570 private List<
IKeyword> GetKeywords()
572 const string LIST_KEYWORDS =
"<PROJECT><CATEGORY><KEYWORDS action=\"list\" /></CATEGORY></PROJECT>";
573 XmlDocument xmlDoc = ExecuteRQL(LIST_KEYWORDS);
574 XmlNodeList xmlNodes = xmlDoc.GetElementsByTagName(
"KEYWORD");
575 IEnumerable<Keyword> categoryKeywords = from curCategory in
Categories
576 select
new Keyword(
this, curCategory.Guid)
579 Category = curCategory
581 return (from XmlElement curNode in xmlNodes select (
IKeyword)
new Keyword(
this, curNode)).Union(categoryKeywords)
585 private List<IPublicationFolder> GetPublicationFolders()
587 const string LIST_PUBLICATION_FOLDERS =
@"<PROJECT><EXPORTFOLDERS action=""list"" /></PROJECT>";
589 XmlDocument xmlDoc = ExecuteRQL(LIST_PUBLICATION_FOLDERS);
590 if (xmlDoc.GetElementsByTagName(
"EXPORTFOLDERS")
595 string.Format(
"Could not retrieve publication folders of project {0}",
this));
597 return (from XmlElement curFolder in xmlDoc.GetElementsByTagName(
"EXPORTFOLDER")
598 select (
IPublicationFolder) new PublicationFolder(this, curFolder.GetGuid())).ToList();
603 const string LIST_PUBLICATION_PACKAGES =
@"<PROJECT><EXPORTPACKET action=""list""/></PROJECT>";
604 XmlDocument xmlDoc = ExecuteRQL(LIST_PUBLICATION_PACKAGES);
605 return (from XmlElement curPackage in xmlDoc.GetElementsByTagName(
"EXPORTPACKET")
611 const string LIST_PUBLISHING_TARGETS =
@"<PROJECT><EXPORTS action=""list""/></PROJECT>";
613 XmlDocument xmlDoc = ExecuteRQL(LIST_PUBLISHING_TARGETS);
615 (from XmlElement curElement in xmlDoc.GetElementsByTagName(
"EXPORT")
621 RecycleBin =
new RecycleBin(
this);
622 PublicationTargets =
new RDList<IPublicationTarget>(GetPublicationTargets,
Caching.Enabled);
623 PublicationFolders =
new RDList<IPublicationFolder>(GetPublicationFolders,
Caching.Enabled);
624 PublicationPackages =
new RDList<IPublicationPackage>(GetPublicationPackages,
Caching.Enabled);
625 InfoAttributes =
new IndexedCachedList<int, IInfoAttribute>(GetInfoAttributes, x => x.Id,
Caching.Enabled);
627 ContentClassFolders =
new ContentClassFolders(
this,
Caching.Enabled);
628 Folders =
new Folders(
this,
Caching.Enabled);
629 ProjectVariants =
new ProjectVariants(
this,
Caching.Enabled);
630 LanguageVariants =
new LanguageVariants(
this,
Caching.Enabled);
632 DatabaseConnections =
new DatabaseConnections(
this,
Caching.Enabled);
633 Syllables =
new Syllables(
this,
Caching.Enabled);
634 Users =
new ProjectUsers(
this,
Caching.Enabled);
636 Workflows =
new ProjectWorkflow(
this,
Caching.Enabled);
638 Keywords =
new RDList<IKeyword>(GetKeywords,
Caching.Enabled);
639 AssignedGroups =
new ProjectGroups(
this,
Caching.Enabled);
641 OnlineUsers =
new NameIndexedRDList<IUser>(GetOnlineUsers,
Caching.Enabled);
643 _clipboard =
new ProjectClipboard(
this);
648 private List<IUser> GetOnlineUsers()
650 const string LIST_ONLINE_USERS =
@"<ADMINISTRATION><USERS action=""connectlist"" projectguid=""{0}""/></ADMINISTRATION>";
651 var doc = ExecuteRQL(LIST_ONLINE_USERS.RQLFormat(
this));
653 var userElements = doc.GetElementsByTagName(
"USER").Cast<XmlElement>();
658 return userElements.Select(x=>
new User(Session, x.GetGuid())).Cast<
IUser>().ToList();
661 private void LoadXml()
663 InitIfPresent(ref _locklevel,
"inhibitlevel", x => (
ProjectLockLevel)
int.Parse(x));
664 InitIfPresent(ref _isLockedBySystem,
"lockedbysystem", BoolConvert);