This project is read-only.

Published date the same for all versions of a page

Topics: Developer Forum, User Forum
Jan 19, 2009 at 1:38 PM
I think I've found a defect:

In the /Edit interface, if I select a page and then click the "Previous Versions" button in the toolbar then all previous versions of the page are listed with the exact same "Published" date.

Wouldn't the correct behavior be to show when the "Save and Publish" action was taken for each version?

Thank you,

Jan 19, 2009 at 6:27 PM
There is a point in maintaining the first published date on the published item. The date can be used in various useful ways, e.g. for news listings. It's the date the information first became available to the public. You wouldn't want this date to change each time the page is saved.

An option would be adding this for versions only, but this would require a new date "LastPublished". What do you think?
Jan 19, 2009 at 7:27 PM
You wouldn't want this date to change each time the page is saved.

I am not sure I was clear enough...

The information I expect to see is when each version of a content item was published (unless it wasn't published in which case the date should be blank), not just the first time the content item was published. For example, if I publish a page today and then make changes and publish the same page again next week I should then see two published dates: One for today's version and one for next week's version.

Currently the versions page in the /Edit interface will, for example, state that version 1 and version 10 were "Published" at the exact time despite that they were published several days apart - that doesn't make any sense.
Jan 19, 2009 at 8:39 PM
Okay, I understand what you're saying. I think you have a point about the version list.

What might be needed is a better distinction between "published page" (as an entity with a trail of versions) and "published version" (as one revision of a page). In my mind the page's published date remains the same regardless of later changes. In the version list it makes sense to know when a certain version was created.

What I'm looking for is perhaps a better word or a combination of words to describe what happens to a version of a page when it is born. In the end it might be best to remove the published information from that list since it's non-sensical and there is no good way of knowing when a version was "published".
Jan 19, 2009 at 8:51 PM
What might be needed is a better distinction between "published page" (as an entity with a trail of versions) and "published version" (as one revision of a page). In my mind the page's published date remains the same regardless of later changes. 

This sounds like a good idea. I would suggest that the table list the date the version was published. A summary at the top (or bottom) of the page could list the "First published date" and "First published version" of the item.

> In the version list it makes sense to know when a certain version was created.

As long as there is a distinction between "created" and "published" yes :-).

> there is no good way of knowing when a version was "published".

I think there should be. It is not uncommon that I am asked "what dide pageX look like last month?" - I would like to be able to supply this information.

Thank you!

Jan 21, 2009 at 12:32 PM
I was looking through the N2 database this morning and I think there is a fundamental flaw in how versions work - the n2Item table stores versions of items and yet sometimes treats them as "just" items. The "Created" column should store the creation date of each version, not of the item. Same for the Published column.

I justify this by pointing out that by storing the same value with the same meaning in multiple rows, you add unnecessary redundancy (this is forgivable if it helps with performance, of course). The worst part, however, is that you are losing data about each version. Please correct me if I am wrong: There is no way to tell when the version was published or even if it was published. This is a critical flaw in my opinion.

I therefore suggest the following changes:

Use "FirstPublished" and "FirstCreated" columns (and corresponding properties) to indicate when the Item was published and created, respectivly. Use "VersionPublished" and "VersionCreated" columns (and corresponding properties) to indicate when the version was published and created, respectivly. The Created and Published columns should then be eliminated to avoid confusion (or kept only for upgrade compatability).

If you can help point me in the right direction, I can put a development resource on this issue to resolve it. Please let me know your thoughts.

Thank you!

Jan 21, 2009 at 6:49 PM
You're correct. The "VersionPublished" information is not recorded anywhere except for the expiration date of the previous version (assuming no version in between has been deleted).

The reason for this is that it was designed with a smaller scope in mind compared to what you need. The same goes for the security model that also is too simple for some.

I think the minumum needed would be an extra VersionPublished date on each version. Is the reason for a VersionCreated different dates for "save and preview" and a subsequent Publish? I'd prefer the Published and Created properties to remain to avoid breaking code.

I have a few other changes to the item table in mind and perhaps it could be a good time to push those as well. I've been postponing to avoid the hassle of upgrade database scripts.
Jan 21, 2009 at 7:33 PM
If you will take the lead and define what you need to be done to make these enhancements, I will assign a resource to complete the tasks you delegate (e.g. the database script). All I ask is that you be explicit in how each feature we implement is to behave - we do not yet have intimiate knowledge of N2, but welcome this opportunity to get more involved.
Jan 22, 2009 at 9:41 AM
Edited Jan 22, 2009 at 12:12 PM
A purely theoretical question, but curious about your opinion:

Do you think the following 2 versioning schemes are feasible:

Scheme 1

1) On each ContentItem edit, catch it's object graph (self+children) via N2.Serialization.Exporter and store to a file system as *.xml.gz
2) Provide a "Version history" form, similar to Step 4 of Installation Wizard, where it would be possible to replace current item with a stored backup for the desired date (i.e."version"). (There's even no need for a specific form, because the import can be done via N2 standard facility!)

Evidently, this scheme couldn't function in real-time because of the Importer/Exporter/file system overhead. On the other hand, it could greatly reduce a clutter in the primary database.

Scheme 2

1) On each ContentItem edit, store a whole backup in a plain XML via N2.Serialization.Exporter.
2) Treat the above plain XML graph as a working copy of a SVN repository and do a commit after each export.
3) Keep a global version list and allow rolling back to a specific global version (revision).

Things to notice:
a) there are .Net based OSS code to support interaction with SVN (SharpDevelop with it's SVN integration to be a proof);
b) despite it's complexity, the advantage of this scheme (as with a former one) is that it doesn't really require any specific GUI from N2 side -- everything can be done either with existing N2 Import/Export function OR by any standard SVN client tools.
Jan 24, 2009 at 12:03 AM
Sure I'd appreciate that. There's a couple of tests here. They could help figuring out the basic usage. I'd say the changes would at least touch contentitem.cs including the clone method, versionmanager.cs, possibly editmanager.cs and definitely versions.aspx. Please ask, I'd be happy to assist along the way.

Sounds interesting. This could actually make it easier to all of the parts along with the page. For scheme 1, do you think this would benefit from beeing stored in the database? The first database change since more than a year is coming up. Scheme 2 sounds very cool, but a tad unpractical to set up ;)
Feb 5, 2009 at 10:18 AM
..another boring, version-related question. What could N2 do if in the db it encounter something like this:

item1 { Type = "ItemType", VersionOf = null }
item2 { Type = "ItemSubType1", VersionOf = item1 }
itemN { Type = "ItemSubTypeN", VersionOf = item1 }

(I'm considering different optimization pathes for an upcoming N2.Workflow monster ;=)
Feb 5, 2009 at 9:20 PM
The data model wouldn't complain but the version's type would be lost if a version is restored. Here's the code.
Feb 9, 2009 at 7:24 PM
Quick update: My team should be able to look at making these improvements in early March. Thanks.
Feb 12, 2009 at 9:55 AM
A very out-of-band question (though, with some VersionOf flavour). I was trying to build N2 source tree against NHibernate (i'll explain a motivation for this below). At last, it happened, so i was able to bootstrap the Templates site, but on "Edit" context menu command for any item, i'm getting this YSOD:

[MappingException: No persister for: System.DateTime]
   NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(String entityName) +103
   NHibernate.Impl.SessionImpl.GetEntityPersister(String entityName, Object obj) +157
   NHibernate.Engine.ForeignKeys.IsTransient(String entityName, Object entity, Nullable`1 assumed, ISessionImplementor session) +117
   NHibernate.Engine.ForeignKeys.GetEntityIdentifierIfNotUnsaved(String entityName, Object entity, ISessionImplementor session) +116
   NHibernate.Type.AnyType.NullSafeSet(IDbCommand st, Object value, Int32 index, Boolean[] settable, ISessionImplementor session) +67
   NHibernate.Type.AnyType.NullSafeSet(IDbCommand st, Object value, Int32 index, ISessionImplementor session) +21
   NHibernate.Loader.Loader.BindNamedParameters(IDbCommand st, IDictionary`2 namedParams, Int32 start, ISessionImplementor session) +380
   NHibernate.Loader.Loader.BindParameterValues(IDbCommand statement, QueryParameters queryParameters, Int32 startIndex, ISessionImplementor session) +60
   NHibernate.Loader.Loader.PrepareQueryCommand(QueryParameters queryParameters, Boolean scroll, ISessionImplementor session) +516
   NHibernate.Hql.Classic.QueryTranslator.GetEnumerable(QueryParameters parameters, ISessionImplementor session) +97
   NHibernate.Engine.Query.HQLQueryPlan.DoIterate(QueryParameters queryParameters, IEventSource session, Nullable`1& isMany, IEnumerable[]& results, IEnumerable& result) +230
   NHibernate.Engine.Query.HQLQueryPlan.PerformIterate(QueryParameters queryParameters, IEventSource session) +38
   NHibernate.Engine.Query.HQLQueryPlan.PerformIterate(QueryParameters queryParameters, IEventSource session) +61
   NHibernate.Impl.SessionImpl.Enumerable(String query, QueryParameters queryParameters) +139
   NHibernate.Impl.QueryImpl.Enumerable() +150
   N2.Persistence.NH.Finder.QueryBuilder.Select() in c:\Users\Taras\Documents\Visual Studio 2008\Projects\n2cms\src\N2\Persistence\NH\Finder\QueryBuilder.cs:362
   N2.Persistence.NH.Finder.QueryBuilder.Select() in c:\Users\Taras\Documents\Visual Studio 2008\Projects\n2cms\src\N2\Persistence\NH\Finder\QueryBuilder.cs:357
   N2.Edit.Edit.CheckRelatedVersions(ContentItem item) +216
   N2.Edit.Edit.OnPreRender(EventArgs e) +31
   System.Web.UI.Control.PreRenderRecursiveInternal() +80
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +842
What the hell it might be? Please, don't bother answering if you it doesn't make sense to you now -- i'll try to investigate further myself.

* * *
Now, regarding motivation for this build. I'd like this exactly version of NH, because it's one compatible with a recent NHibernate.Linq from NHContrib trunk. In this NHibernate.Linq they've included some interesting stuff, such as NHibernateContext class, that could help in building ADO.Net Data Service over N2. There'll be even more challenges to overcome, but it's sorta another sad story even longer than this post :-/
Feb 12, 2009 at 9:59 PM
Don't really know sorry. Could it be related to nullable DateTimes?