2009-06-19 07:39:16 +00:00
using System ;
using System.Collections.Generic ;
using System.Text ;
using System.Web.UI ;
using System.Configuration.Provider ;
using System.Web ;
2009-07-13 14:51:26 +00:00
using System.Linq ;
2009-07-16 14:24:37 +00:00
using umbraco.presentation.ClientDependency.Controls ;
2009-06-19 07:39:16 +00:00
namespace umbraco.presentation.ClientDependency.Providers
{
public abstract class ClientDependencyProvider : ProviderBase
{
protected Control DependantControl { get ; private set ; }
2009-07-28 16:22:14 +00:00
protected HashSet < IClientDependencyPath > FolderPaths { get ; private set ; }
2009-06-19 09:32:18 +00:00
protected List < IClientDependencyFile > AllDependencies { get ; private set ; }
/// <summary>
/// Set to true to disable composite scripts so all scripts/css comes through as individual files.
/// </summary>
public bool IsDebugMode { get ; set ; }
2009-06-19 07:39:16 +00:00
protected abstract void RegisterJsFiles ( List < IClientDependencyFile > jsDependencies ) ;
protected abstract void RegisterCssFiles ( List < IClientDependencyFile > cssDependencies ) ;
2009-07-13 14:51:26 +00:00
protected abstract void ProcessSingleJsFile ( string js ) ;
protected abstract void ProcessSingleCssFile ( string css ) ;
2009-06-19 07:39:16 +00:00
2009-06-19 09:32:18 +00:00
public override void Initialize ( string name , System . Collections . Specialized . NameValueCollection config )
{
2009-07-28 16:22:14 +00:00
IsDebugMode = true ;
2009-06-19 09:32:18 +00:00
if ( config ! = null & & config [ "isDebug" ] ! = null )
{
bool isDebug ;
if ( bool . TryParse ( config [ "isDebug" ] , out isDebug ) )
IsDebugMode = isDebug ;
}
base . Initialize ( name , config ) ;
}
2009-07-28 16:22:14 +00:00
public void RegisterDependencies ( Control dependantControl , ClientDependencyCollection dependencies , HashSet < IClientDependencyPath > paths )
2009-06-19 07:39:16 +00:00
{
DependantControl = dependantControl ;
2009-07-07 14:27:03 +00:00
AllDependencies = new List < IClientDependencyFile > ( dependencies ) ;
2009-06-19 07:39:16 +00:00
FolderPaths = paths ;
UpdateFilePaths ( ) ;
2009-07-28 16:22:14 +00:00
List < IClientDependencyFile > jsDependencies = AllDependencies
. Where ( x = > x . DependencyType = = ClientDependencyType . Javascript )
. ToList ( ) ;
List < IClientDependencyFile > cssDependencies = AllDependencies
. Where ( x = > x . DependencyType = = ClientDependencyType . Css )
. ToList ( ) ;
2009-06-19 07:39:16 +00:00
// sort by priority
jsDependencies . Sort ( ( a , b ) = > a . Priority . CompareTo ( b . Priority ) ) ;
cssDependencies . Sort ( ( a , b ) = > a . Priority . CompareTo ( b . Priority ) ) ;
2009-06-19 09:32:18 +00:00
RegisterCssFiles ( cssDependencies . ConvertAll < IClientDependencyFile > ( a = > { return ( IClientDependencyFile ) a ; } ) ) ;
2009-06-19 07:39:16 +00:00
RegisterJsFiles ( jsDependencies . ConvertAll < IClientDependencyFile > ( a = > { return ( IClientDependencyFile ) a ; } ) ) ;
2009-07-26 15:13:15 +00:00
//Register all startup scripts in order
RegisterStartupScripts ( dependencies
. Where ( x = > ! string . IsNullOrEmpty ( x . InvokeJavascriptMethodOnLoad ) )
. OrderBy ( x = > x . Priority )
. ToList ( ) ) ;
2009-06-19 07:39:16 +00:00
}
2009-07-26 15:13:15 +00:00
/// <summary>
/// Registers all of the methods/scripts to be invoked that have been set in the InvokeJavaScriptMethodOnLoad propery
/// for each dependent js script.
/// </summary>
/// <param name="jsDependencies"></param>
protected virtual void RegisterStartupScripts ( List < IClientDependencyFile > dependencies )
{
2009-07-28 16:22:14 +00:00
//foreach (var js in dependencies)
//{
// DependantControl.Page.ClientScript.RegisterStartupScript(this.GetType(), js.GetHashCode().ToString(), js.InvokeJavascriptMethodOnLoad, true);
//}
2009-07-26 15:13:15 +00:00
}
2009-06-19 07:39:16 +00:00
/// <summary>
2009-07-13 14:51:26 +00:00
/// Returns a list of urls. The array will consist of only one entry if
/// none of the dependencies are tagged as DoNotOptimize, otherwise, if any of them are,
/// this will return the path to the file.
///
/// For the optimized files, the full url with the encoded query strings for the handler which will process the composite list
/// of dependencies. The handler will compbine, compress, minify (if JS), and output cache the results
/// based on a hash key of the base64 encoded string.
2009-06-19 07:39:16 +00:00
/// </summary>
/// <param name="dependencies"></param>
/// <param name="groupName"></param>
2009-07-13 14:51:26 +00:00
/// <remarks>
/// If the DoNotOptimize setting has been set for any of the dependencies in the list, then this will ignore them.
/// </remarks>
2009-06-19 07:39:16 +00:00
/// <returns></returns>
2009-07-13 14:51:26 +00:00
protected List < string > ProcessCompositeList ( List < IClientDependencyFile > dependencies , ClientDependencyType type )
{
List < string > rVal = new List < string > ( ) ;
2009-07-20 14:39:48 +00:00
if ( dependencies . Count = = 0 )
return rVal ;
2009-07-13 14:51:26 +00:00
//build the combined composite list url
string handler = "{0}?s={1}&t={2}" ;
StringBuilder files = new StringBuilder ( ) ;
foreach ( IClientDependencyFile a in dependencies . Where ( x = > ! x . DoNotOptimize ) )
{
files . Append ( a . FilePath + ";" ) ;
}
string combinedurl = string . Format ( handler , CompositeDependencyHandler . HandlerFileName , HttpContext . Current . Server . UrlEncode ( EncodeTo64 ( files . ToString ( ) ) ) , type . ToString ( ) ) ;
rVal . Add ( combinedurl ) ;
//add any urls that are not to be optimized
foreach ( IClientDependencyFile a in dependencies . Where ( x = > x . DoNotOptimize ) )
{
rVal . Add ( a . FilePath ) ;
}
//if (url.Length > CompositeDependencyHandler.MaxHandlerUrlLength)
// throw new ArgumentOutOfRangeException("The number of files in the composite group " + groupName + " creates a url handler address that exceeds the CompositeDependencyHandler MaxHandlerUrlLength. Reducing the amount of files in this composite group should fix the issue");
return rVal ;
}
2009-06-19 07:39:16 +00:00
private string EncodeTo64 ( string toEncode )
{
byte [ ] toEncodeAsBytes = System . Text . ASCIIEncoding . ASCII . GetBytes ( toEncode ) ;
string returnValue = System . Convert . ToBase64String ( toEncodeAsBytes ) ;
return returnValue ;
}
/// <summary>
/// Ensures the correctly resolved file path is set for each dependency (i.e. so that ~ are taken care of) and also
/// prefixes the file path with the correct base path specified for the PathNameAlias if specified.
/// </summary>
/// <param name="dependencies"></param>
/// <param name="paths"></param>
/// <param name="control"></param>
private void UpdateFilePaths ( )
{
2009-06-19 09:32:18 +00:00
foreach ( IClientDependencyFile dependency in AllDependencies )
2009-06-19 07:39:16 +00:00
{
if ( ! string . IsNullOrEmpty ( dependency . PathNameAlias ) )
{
2009-07-28 16:22:14 +00:00
List < IClientDependencyPath > paths = FolderPaths . ToList ( ) ;
IClientDependencyPath path = paths . Find (
delegate ( IClientDependencyPath p )
2009-06-19 07:39:16 +00:00
{
return p . Name = = dependency . PathNameAlias ;
}
) ;
if ( path = = null )
{
throw new NullReferenceException ( "The PathNameAlias specified for dependency " + dependency . FilePath + " does not exist in the ClientDependencyPathCollection" ) ;
}
string basePath = path . ResolvedPath . EndsWith ( "/" ) ? path . ResolvedPath : path . ResolvedPath + "/" ;
dependency . FilePath = basePath + dependency . FilePath ;
}
else
{
dependency . FilePath = DependantControl . ResolveUrl ( dependency . FilePath ) ;
}
}
}
2009-07-26 15:13:15 +00:00
2009-06-19 07:39:16 +00:00
}
}