I've noticed that the settings file (autofolders.config) has been growing and I'm think it needs tidied up.
However, this will mean the next version will not be backwards compatible. Does this matter to anyone?
The changes are to move the settings that should be DocType settings out of the 'folder provider' section. Hopefully creating a more correct, flexible and easily understandable config file.
Chris, makes perfect sense! I'd just make sure to keep the old versions on your project site as well!
Btw, doesn't the second xml config have a small error on the second folder provider (you've still included the FolderDocType property which you probably want to avoid there).
I like the newer version better too. That way if you want a date folder for both events and news, you only have to add one line instead of a renamed Folder Provider (different doctypes).
One idea that I had was that it would be nice to override the field that folder dates are created off of. Right now, it goes off of the date created. It would be nice to be able to override that field with a user submitted one. That way, if I'm creating news and the news article had a date that is different then the current date, the folders would be created off of the date of the actual article rather than the date created. In example of this is that if we had a press release that we wanted released on Nov 1. If I created it today, without publishing, the folder structure woudl be /2009/10/22/pressrelease rather than /2009/11/01/pressrelease like it should.
So I've been playing around with the autofolders to work on basing the date on off of either the created date or a field name labeled 'displayDate'. Ideally, the date field would be a setting in the .config file, but I haven't played around with that since it deals with a major rewriting off the functionality.
As for the code, I had to switch the event handler to .AfterPublish. Once I did this, I could then use the data field from my document type. Then had to switch around the functionality in DateFolderProvider.cs to handle switching from one folder to the next. Ie. If I needed to switch from /2009/10/05 to /2009/11/05 and the folders were set correctly.
Since the project is open source, I've included the two methods that I modified below. I'd be interested to hear what people have to say in making the code more efficient.
public override int FindValidFolderId(Document newDocument)
{
string displayDate = newDocument.getProperty("displayDate").Value.ToString();
string currentDay = string.Empty;
string currentMonth = string.Empty;
string currentYear = string.Empty;
if (displayDate != string.Empty)
{
currentDay = umbraco.library.FormatDateTime(displayDate, this.DayFormat);
currentMonth = umbraco.library.FormatDateTime(displayDate, this.MonthFormat);
currentYear = umbraco.library.FormatDateTime(displayDate, this.YearFormat);
}
else
{
currentDay = newDocument.CreateDateTime.ToString(this.DayFormat);
currentMonth = newDocument.CreateDateTime.ToString(this.MonthFormat);
currentYear = newDocument.CreateDateTime.ToString(this.YearFormat);
}
int validFolderId = -1;
if (newDocument.Level > 1)
{
CMSNode parentNode = newDocument.Parent;
CMSNode startSearch = parentNode;
// Firstly, check if user is adding document to auto-created folder (e.g. 2009/09)
if (!m_includeDayLevel && parentNode.Level > 1)
{
CMSNode grandParentDocument = parentNode.Parent;
if (grandParentDocument.Text == currentYear)
{
if (parentNode.Text == currentMonth)
return parentNode.Id;
startSearch = grandParentDocument.Parent;
}
else
{
int year = 0;
if (Int32.TryParse(grandParentDocument.Text, out year))
if (year > 1900 && year < 2100)
startSearch = grandParentDocument.Parent;
}
}
else if (this.m_includeDayLevel && parentNode.Level > 2)
{
CMSNode grandParentDocument = parentNode.Parent;
CMSNode greatGrandParentDocument = grandParentDocument.Parent;
if (greatGrandParentDocument.Text == currentYear)
{
if (grandParentDocument.Text == currentMonth && parentNode.Text == currentDay)
return parentNode.Id;
startSearch = greatGrandParentDocument.Parent;
}
else
{
int year = 0;
if (Int32.TryParse(greatGrandParentDocument.Text, out year))
if (year > 1900 && year < 2100)
startSearch = greatGrandParentDocument.Parent;
}
}
// Secondly check for child folder that was previously auto-created
foreach (IconI yearIcon in startSearch.Children)
{
if (yearIcon.Text == currentYear)
{
foreach (IconI monthIcon in yearIcon.Children)
{
if (!this.m_includeDayLevel && monthIcon.Text == currentMonth)
{
validFolderId = monthIcon.Id;
break;
}
else if (monthIcon.Text == currentMonth)
{
foreach (IconI dayIcon in monthIcon.Children)
{
if (dayIcon.Text == currentDay)
{
validFolderId = dayIcon.Id;
break;
}
}
}
}
}
}
}
return validFolderId;
}
public override int CreateFolderStructure(Document newDocument)
{
string displayDate = newDocument.getProperty("displayDate").Value.ToString();
string currentDay = string.Empty;
string currentMonth = string.Empty;
string currentYear = string.Empty;
if (displayDate != string.Empty)
{
currentDay = umbraco.library.FormatDateTime(displayDate, this.DayFormat);
currentMonth = umbraco.library.FormatDateTime(displayDate, this.MonthFormat);
currentYear = umbraco.library.FormatDateTime(displayDate, this.YearFormat);
}
else
{
currentDay = newDocument.CreateDateTime.ToString(this.DayFormat);
currentMonth = newDocument.CreateDateTime.ToString(this.MonthFormat);
currentYear = newDocument.CreateDateTime.ToString(this.YearFormat);
}
string folderDocTypeAlias = this.FolderDocTypeAlias;
CMSNode startSearch = newDocument;
int yearDocumentId = -1;
if (newDocument.Level > 1)
{
CMSNode parentNode = newDocument.Parent;
startSearch = parentNode;
// Firstly, check if user is adding document to auto-created folder (e.g. 2009/09)
if (!this.m_includeDayLevel && parentNode.Level > 1)
{
CMSNode grandParentDocument = parentNode.Parent;
if (grandParentDocument.Text == currentYear)
{
if (parentNode.Text == currentMonth)
return parentNode.Id;
startSearch = grandParentDocument.Parent;
}
else
{
int year = 0;
if (Int32.TryParse(grandParentDocument.Text, out year))
if (year > 1900 && year < 2100)
startSearch = grandParentDocument.Parent;
}
}
else if (this.m_includeDayLevel && parentNode.Level > 2)
{
CMSNode grandParentDocument = parentNode.Parent;
CMSNode greatGrandParentDocument = grandParentDocument.Parent;
if (greatGrandParentDocument.Text == currentYear)
{
if (grandParentDocument.Text == currentMonth && parentNode.Text == currentDay)
return parentNode.Id;
startSearch = greatGrandParentDocument.Parent;
}
else
{
int year = 0;
if (Int32.TryParse(greatGrandParentDocument.Text, out year))
{
if (year > 1900 && year < 2100)
{
startSearch = greatGrandParentDocument.Parent;
}
}
}
}
bool yearExists = false;
bool monthExists = false;
bool dayExists = false;
// Secondly check for child folder that was previously auto-created
foreach (IconI yearIcon in startSearch.Children)
{
if (yearIcon.Text == currentYear)
{
yearDocumentId = yearIcon.Id;
foreach (IconI monthIcon in yearIcon.Children)
{
if (!this.m_includeDayLevel && monthIcon.Text == currentMonth)
{
return monthIcon.Id;
}
else if (monthIcon.Text == currentMonth)
{
foreach (IconI dayIcon in monthIcon.Children)
{
if (dayIcon.Text == currentDay)
{
return dayIcon.Id;
}
}
}
}
}
}
}
if (yearDocumentId <= 0)
{
Document document = Document.MakeNew(
currentYear,
DocumentType.GetByAlias(folderDocTypeAlias),
newDocument.User,
startSearch.Id);
document.Publish(newDocument.User);
library.UpdateDocumentCache(document.Id);
yearDocumentId = document.Id;
}
// Immediately create month folder
if (!this.m_includeDayLevel)
{
Document document2 = Document.MakeNew(
currentMonth,
DocumentType.GetByAlias(folderDocTypeAlias),
newDocument.User,
yearDocumentId);
document2.Publish(newDocument.User);
library.UpdateDocumentCache(document2.Id);
return document2.Id;
}
else
{
// check for month folder, then create day folder
CMSNode yearIcon = new CMSNode(yearDocumentId);
int monthDocumentId = -1;
foreach (IconI monthIcon in yearIcon.Children)
{
if (monthIcon.Text == currentMonth)
{
monthDocumentId = monthIcon.Id;
break;
}
}
if (monthDocumentId <= 0)
{
Document document2 = Document.MakeNew(
currentMonth,
DocumentType.GetByAlias(folderDocTypeAlias),
newDocument.User,
yearDocumentId);
document2.Publish(newDocument.User);
library.UpdateDocumentCache(document2.Id);
monthDocumentId = document2.Id;
}
Document document3 = Document.MakeNew(
currentDay,
DocumentType.GetByAlias(folderDocTypeAlias),
newDocument.User,
monthDocumentId);
document3.Publish(newDocument.User);
library.UpdateDocumentCache(document3.Id);
return document3.Id;
}
}
}
}
Settings & Configuration Improvements
Hi,
I've noticed that the settings file (autofolders.config) has been growing and I'm think it needs tidied up.
However, this will mean the next version will not be backwards compatible. Does this matter to anyone?
The changes are to move the settings that should be DocType settings out of the 'folder provider' section. Hopefully creating a more correct, flexible and easily understandable config file.
CURRENT FILE
NEW FILE
Does this make sense?
Does anyone have an opinion/preference either way?
Chris
Chris, makes perfect sense! I'd just make sure to keep the old versions on your project site as well!
Btw, doesn't the second xml config have a small error on the second folder provider (you've still included the FolderDocType property which you probably want to avoid there).
Cheers,
/Dirk
One small addition:
Would'nt it be more efficient to add the properties as an attribute?
I never used this package yet so if it does'nt make sense just ignore me.
Ron
Dirk - I'll keep the older versions available. It's a shame there's not an 'archive' option.
Ron - If you're thinking about Control properties then you've misunderstood the package.
Thanks both for your thoughts.
I like the newer version better too. That way if you want a date folder for both events and news, you only have to add one line instead of a renamed Folder Provider (different doctypes).
One idea that I had was that it would be nice to override the field that folder dates are created off of. Right now, it goes off of the date created. It would be nice to be able to override that field with a user submitted one. That way, if I'm creating news and the news article had a date that is different then the current date, the folders would be created off of the date of the actual article rather than the date created. In example of this is that if we had a press release that we wanted released on Nov 1. If I created it today, without publishing, the folder structure woudl be /2009/10/22/pressrelease rather than /2009/11/01/pressrelease like it should.
Great project though!
-C
Great suggestion Chad, I will include it in the next release.
So I've been playing around with the autofolders to work on basing the date on off of either the created date or a field name labeled 'displayDate'. Ideally, the date field would be a setting in the .config file, but I haven't played around with that since it deals with a major rewriting off the functionality.
As for the code, I had to switch the event handler to .AfterPublish. Once I did this, I could then use the data field from my document type. Then had to switch around the functionality in DateFolderProvider.cs to handle switching from one folder to the next. Ie. If I needed to switch from /2009/10/05 to /2009/11/05 and the folders were set correctly.
Since the project is open source, I've included the two methods that I modified below. I'd be interested to hear what people have to say in making the code more efficient.
Hi Chad,
I'm glad you've been able to change the code to suit your needs!
I've (just) released AutoFolders v2.0 beta, which now supports this functionality. Please give it a try and let me know how you get on.
Maybe I should move the code to codeplex to support contributions better?
Cheers,
Chris
is working on a reply...