using System;
using System.ComponentModel;
using System.Web;
using System.Web.Security;
using System.Xml.Linq;
using System.Xml.XPath;
using Umbraco.Core;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Dynamics;
using Umbraco.Core.Models;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Xml;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
using System.Collections.Generic;
using System.IO;
using System.Web.Mvc;
using System.Web.Routing;
using Umbraco.Core.Cache;
namespace Umbraco.Web
{
///
/// A helper class that provides many useful methods and functionality for using Umbraco in templates
///
public class UmbracoHelper : IUmbracoComponentRenderer
{
private readonly UmbracoContext _umbracoContext;
private readonly IPublishedContent _currentPage;
private readonly ITypedPublishedContentQuery _typedQuery;
private readonly IDynamicPublishedContentQuery _dynamicQuery;
private readonly HtmlStringUtilities _stringUtilities = new HtmlStringUtilities();
private IUmbracoComponentRenderer _componentRenderer;
private PublishedContentQuery _query;
private MembershipHelper _membershipHelper;
private TagQuery _tag;
private IDataTypeService _dataTypeService;
private UrlProvider _urlProvider;
private ICultureDictionary _cultureDictionary;
///
/// Lazy instantiates the tag context
///
public TagQuery TagQuery
{
//TODO: Unfortunately we cannot change this return value to be ITagQuery
// since it's a breaking change, need to fix it for v8
// http://issues.umbraco.org/issue/U4-6899
get
{
return _tag ??
(_tag = new TagQuery(UmbracoContext.Application.Services.TagService,
_typedQuery ?? ContentQuery));
}
}
///
/// Lazy instantiates the query context if not specified in the constructor
///
public PublishedContentQuery ContentQuery
{
get
{
//If the content query doesn't exist it will either be created with the ITypedPublishedContentQuery, IDynamicPublishedContentQuery
// used to construct this instance or with the content caches of the UmbracoContext
return _query ??
(_query = _typedQuery != null
? new PublishedContentQuery(_typedQuery, _dynamicQuery)
: new PublishedContentQuery(UmbracoContext.ContentCache, UmbracoContext.MediaCache));
}
}
///
/// Helper method to ensure an umbraco context is set when it is needed
///
public UmbracoContext UmbracoContext
{
get
{
if (_umbracoContext == null)
{
throw new NullReferenceException("No " + typeof(UmbracoContext) + " reference has been set for this " + typeof(UmbracoHelper) + " instance");
}
return _umbracoContext;
}
}
///
/// Lazy instantiates the membership helper if not specified in the constructor
///
public MembershipHelper MembershipHelper
{
get { return _membershipHelper ?? (_membershipHelper = new MembershipHelper(UmbracoContext)); }
}
///
/// Lazy instantiates the UrlProvider if not specified in the constructor
///
public UrlProvider UrlProvider
{
get { return _urlProvider ?? (_urlProvider = UmbracoContext.UrlProvider); }
}
///
/// Lazy instantiates the IDataTypeService if not specified in the constructor
///
public IDataTypeService DataTypeService
{
get { return _dataTypeService ?? (_dataTypeService = UmbracoContext.Application.Services.DataTypeService); }
}
///
/// Lazy instantiates the IUmbracoComponentRenderer if not specified in the constructor
///
public IUmbracoComponentRenderer UmbracoComponentRenderer
{
get { return _componentRenderer ?? (_componentRenderer = new UmbracoComponentRenderer(UmbracoContext)); }
}
#region Constructors
///
/// Empty constructor to create an umbraco helper for access to methods that don't have dependencies
///
public UmbracoHelper()
{
}
///
/// Constructor accepting all dependencies
///
///
///
///
///
///
///
///
///
///
///
///
/// This constructor can be used to create a testable UmbracoHelper
///
public UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content,
ITypedPublishedContentQuery typedQuery,
IDynamicPublishedContentQuery dynamicQuery,
ITagQuery tagQuery,
IDataTypeService dataTypeService,
UrlProvider urlProvider,
ICultureDictionary cultureDictionary,
IUmbracoComponentRenderer componentRenderer,
MembershipHelper membershipHelper)
{
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
if (content == null) throw new ArgumentNullException("content");
if (typedQuery == null) throw new ArgumentNullException("typedQuery");
if (dynamicQuery == null) throw new ArgumentNullException("dynamicQuery");
if (tagQuery == null) throw new ArgumentNullException("tagQuery");
if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
if (urlProvider == null) throw new ArgumentNullException("urlProvider");
if (cultureDictionary == null) throw new ArgumentNullException("cultureDictionary");
if (componentRenderer == null) throw new ArgumentNullException("componentRenderer");
if (membershipHelper == null) throw new ArgumentNullException("membershipHelper");
_umbracoContext = umbracoContext;
_tag = new TagQuery(tagQuery);
_dataTypeService = dataTypeService;
_urlProvider = urlProvider;
_cultureDictionary = cultureDictionary;
_componentRenderer = componentRenderer;
_membershipHelper = membershipHelper;
_currentPage = content;
_typedQuery = typedQuery;
_dynamicQuery = dynamicQuery;
}
[Obsolete("Use the constructor specifying all dependencies")]
[EditorBrowsable(EditorBrowsableState.Never)]
public UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content, PublishedContentQuery query)
: this(umbracoContext)
{
if (content == null) throw new ArgumentNullException("content");
if (query == null) throw new ArgumentNullException("query");
_currentPage = content;
_query = query;
}
///
/// Custom constructor setting the current page to the parameter passed in
///
///
///
public UmbracoHelper(UmbracoContext umbracoContext, IPublishedContent content)
: this(umbracoContext)
{
if (content == null) throw new ArgumentNullException("content");
_currentPage = content;
}
///
/// Standard constructor setting the current page to the page that has been routed to
///
///
public UmbracoHelper(UmbracoContext umbracoContext)
{
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
if (umbracoContext.RoutingContext == null) throw new NullReferenceException("The RoutingContext on the UmbracoContext cannot be null");
_umbracoContext = umbracoContext;
if (_umbracoContext.IsFrontEndUmbracoRequest)
{
_currentPage = _umbracoContext.PublishedContentRequest.PublishedContent;
}
}
[Obsolete("Use the constructor specifying all dependencies")]
[EditorBrowsable(EditorBrowsableState.Never)]
public UmbracoHelper(UmbracoContext umbracoContext, PublishedContentQuery query)
: this(umbracoContext)
{
if (query == null) throw new ArgumentNullException("query");
_query = query;
}
#endregion
///
/// Returns the current IPublishedContent item assigned to the UmbracoHelper
///
///
/// Note that this is the assigned IPublishedContent item to the UmbracoHelper, this is not necessarily the Current IPublishedContent item
/// being rendered. This IPublishedContent object is contextual to the current UmbracoHelper instance.
///
/// In some cases accessing this property will throw an exception if there is not IPublishedContent assigned to the Helper
/// this will only ever happen if the Helper is constructed with an UmbracoContext and it is not a front-end request
///
/// Thrown if the UmbracoHelper is constructed with an UmbracoContext and it is not a front-end request
public IPublishedContent AssignedContentItem
{
get
{
if (_currentPage == null)
throw new InvalidOperationException("Cannot return the " + typeof(IPublishedContent).Name + " because the " + typeof(UmbracoHelper).Name + " was constructed with an " + typeof(UmbracoContext).Name + " and the current request is not a front-end request.");
return _currentPage;
}
}
///
/// Renders the template for the specified pageId and an optional altTemplateId
///
///
/// If not specified, will use the template assigned to the node
///
public IHtmlString RenderTemplate(int pageId, int? altTemplateId = null)
{
return UmbracoComponentRenderer.RenderTemplate(pageId, altTemplateId);
}
#region RenderMacro
///
/// Renders the macro with the specified alias.
///
/// The alias.
///
public IHtmlString RenderMacro(string alias)
{
return UmbracoComponentRenderer.RenderMacro(alias, new { });
}
///
/// Renders the macro with the specified alias, passing in the specified parameters.
///
/// The alias.
/// The parameters.
///
public IHtmlString RenderMacro(string alias, object parameters)
{
return UmbracoComponentRenderer.RenderMacro(alias, parameters.ToDictionary