A lot good information and responses. Thank you. I have come up with the solution. Let me elaborate.
The requirement: All registered users (Who are not editors or Administrators) whose roles allow them to add a page via the user contribution, should be able to do so. They will not have the ability to edit once the page is saved. Then, under pending documents when an editor logs in they can see all the pages that are pending approval and either publish them or reject them. If it is rejected please send the user who posted the page an email explaining why.
This was accomplished by cloning and modifying the users contribution list web part so that after the user clicks save the contribution web part edit form closes and either goes back to just the Add button or to the list depending on how it is configured.
The modification for the cloned web part. ~/CMSWebparts/UserContributions/ContributionsList.ascx
private void CMSForm_OnAfterSave(object sender, EventArgs e)
{
if (!StandAlone)
{
// Reload data after saving the document
PagePlaceholder.ClearCache();
PagePlaceholder.ReloadData();
if(CloseFormAfterSave)
{
URLHelper.Redirect("~/" + DocumentContext.CurrentDocument.NodeAliasPath);
}
}
}
Here you also see "CloseFormAfterSave", this is a Boolean web part setting I added to the cloned web part and I am picking it up from the properties above. This allows me to configure the web part to either the standard behavior which is to stay open after save or to close. Not elegant but works.
Next create a workflow for your page types. Add a step between edit and publish. I call mine "Pending", configure the scope and the security so that the individuals or roles will be able to see them and approve/reject them.
Finally create a class file in your App_Code folder somewhere and call it what you like. Below is the code. It is taking advantage of global events. Notice the comments. It is configured for my needs but if you are so inspired modify it for your own purposes. My complete class is below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using CMS.Base;
using CMS.DocumentEngine;
using CMS.SiteProvider;
using CMS.Membership;
using CMS.WorkflowEngine;
using CMS.Base;
using CMS.DocumentEngine;
using CMS.PortalEngine;
[CustomDocumentEvents]
public partial class CMSModuleLoader
{
/// <summary>
/// Attribute class that ensures the loading of custom handlers.
/// </summary>
private class CustomDocumentEventsAttribute : CMSLoaderAttribute
{
/// <summary>
/// The system executes the Init method of the CMSModuleLoader attributes when the application starts.
/// </summary>
public override void Init()
{
// Assigns custom handlers to events
DocumentEvents.Update.After += Document_Update_After;
DocumentEvents.Insert.After += Document_Insert_After;
DocumentEvents.InsertLink.Before += Document_InsertLink_Before;
}
private void Document_Insert_After(object sender, DocumentEventArgs e)
{
//Add custom actions here
}
private void Document_InsertLink_Before(object sender, DocumentEventArgs e)
{
// Add custom actions here
}
private void Document_Update_After(object sender, DocumentEventArgs e)
{
//Check is site is in Live Site view mode. In Backend this will not fire. Manual workflow processing will be done.
bool isLiveSite = PortalContext.ViewMode.IsLiveSite();
if (isLiveSite)
{
SetWorkFlowToPending(e.Node.NodeID);
}
}
//This will set the worflow on the document to the next status of pending so it will be
//reviewable in pending documents by the configured users/roles in the workflow's settings.
private void SetWorkFlowToPending(int nodeID)
{
//Get Tree for current user.
TreeProvider tree = new TreeProvider(MembershipContext.AuthenticatedUser);
// Get the document
CMS.DocumentEngine.TreeNode node = tree.SelectSingleNode(nodeID);
if (node != null)
{
//Get Workflow Manager Instance
WorkflowManager workflowManager = WorkflowManager.GetInstance(tree);
//Get Workflow for node.
WorkflowInfo workflow = workflowManager.GetNodeWorkflow(node);
// Check if the document uses workflow
if (workflow != null)
{
// Check if the workflow doesn't use automatic publishing, otherwise, documents can't change workflow steps.
if (!workflow.WorkflowAutoPublishChanges)
{
//If node is checked out, this will check it in so workflow can be updated.
if (node.IsCheckedOut)
{
VersionManager versionmanager = VersionManager.GetInstance(tree);
// Check in the document if it is checked out depending on settings and workflow.
versionmanager.CheckIn(node, null, "Automatic from Live Site Insert.");
}
// Move the document to the next step
workflowManager.MoveToNextStep(node, "Automatic from Live Site Insert.");
//Comment out above and uncomment below if you want to check if user has proper permissions.
// Check if the current user can move the document to the next step
//if (workflowManager.CheckStepPermissions(node, WorkflowActionEnum.Approve))
//{
// // Move the document to the next step
// workflowManager.MoveToNextStep(node, null);
//}
}
}
}
}
}
}
In the end what I ended up with is a way for registered users of the website allowed to insert pages (Documents) that will be put in a pending workflow status, reviewed, approved or rejected and then published. The solution used a cloned contribution web part. A Workflow. A Global Event Handler.