PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/CompositeC1/Composite.Workflows/Plugins/Elements/ElementProviders/MethodBasedFunctionProviderElementProvider/EditInlineFunctionWorkflow.cs

#
C# | 409 lines | 308 code | 83 blank | 18 comment | 38 complexity | 6a56c0bbd3e5723b0ff5da603f7941b7 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /*
  2. * The contents of this web application are subject to the Mozilla Public License Version
  3. * 1.1 (the "License"); you may not use this web application except in compliance with
  4. * the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/.
  5. *
  6. * Software distributed under the License is distributed on an "AS IS" basis,
  7. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  8. * for the specific language governing rights and limitations under the License.
  9. *
  10. * The Original Code is owned by and the Initial Developer of the Original Code is
  11. * Composite A/S (Danish business reg.no. 21744409). All Rights Reserved
  12. *
  13. * Section 11 of the License is EXPRESSLY amended to include a provision stating
  14. * that any dispute, including but not limited to disputes related to the enforcement
  15. * of the License, to which Composite A/S as owner of the Original Code, as Initial
  16. * Developer or in any other role, becomes a part to shall be governed by Danish law
  17. * and be initiated before the Copenhagen City Court ("K�benhavns Byret")
  18. */
  19. using System;
  20. using System.Collections.Generic;
  21. using System.Globalization;
  22. using System.Linq;
  23. using System.Reflection;
  24. using System.Text;
  25. using System.Threading;
  26. using System.Transactions;
  27. using System.Web;
  28. using System.Web.UI;
  29. using System.Workflow.Runtime;
  30. using System.Xml.Linq;
  31. using System.Xml.Serialization;
  32. using Composite.C1Console.Actions;
  33. using Composite.C1Console.Users;
  34. using Composite.C1Console.Workflow;
  35. using Composite.C1Console.Workflow.Foundation;
  36. using Composite.Core.Extensions;
  37. using Composite.Core.Linq;
  38. using Composite.Core.ResourceSystem;
  39. using Composite.Core.Types;
  40. using Composite.Core.WebClient.FlowMediators.FormFlowRendering;
  41. using Composite.Core.WebClient.FunctionCallEditor;
  42. using Composite.Core.WebClient.Renderings.Page;
  43. using Composite.Core.WebClient.State;
  44. using Composite.Data;
  45. using Composite.Data.Transactions;
  46. using Composite.Data.Types;
  47. using Composite.Functions;
  48. using Composite.Functions.Inline;
  49. using Composite.Functions.ManagedParameters;
  50. using Composite.Core.Serialization;
  51. namespace Composite.Workflows.Plugins.Elements.ElementProviders.MethodBasedFunctionProviderElementProvider
  52. {
  53. [EntityTokenLock]
  54. [AllowPersistingWorkflow(WorkflowPersistingType.Idle)]
  55. public sealed partial class EditInlineFunctionWorkflow : Composite.C1Console.Workflow.Activities.FormsWorkflow
  56. {
  57. public EditInlineFunctionWorkflow()
  58. {
  59. InitializeComponent();
  60. }
  61. private void initializeCodeActivity_InitBindings_ExecuteCode(object sender, EventArgs e)
  62. {
  63. IInlineFunction functionInfo = this.GetDataItemFromEntityToken<IInlineFunction>();
  64. this.Bindings.Add("Function", functionInfo);
  65. this.Bindings.Add("PageId", PageManager.GetChildrenIDs(Guid.Empty).FirstOrDefault());
  66. if (UserSettings.ActiveLocaleCultureInfo != null)
  67. {
  68. List<KeyValuePair<string, string>> activeCulturesDictionary = UserSettings.ActiveLocaleCultureInfos.Select(f => new KeyValuePair<string, string>(f.Name, DataLocalizationFacade.GetCultureTitle(f))).ToList();
  69. this.Bindings.Add("ActiveCultureName", UserSettings.ActiveLocaleCultureInfo.Name);
  70. this.Bindings.Add("ActiveCulturesList", activeCulturesDictionary);
  71. }
  72. this.Bindings.Add("PageDataScopeName", DataScopeIdentifier.AdministratedName);
  73. this.Bindings.Add("PageDataScopeList", new Dictionary<string, string>
  74. {
  75. { DataScopeIdentifier.AdministratedName, GetText("EditInlineFunctionWorkflow.AdminitrativeScope.Label") },
  76. { DataScopeIdentifier.PublicName, GetText("EditInlineFunctionWorkflow.PublicScope.Label") }
  77. });
  78. this.Bindings.Add("FunctionCode", functionInfo.GetFunctionCode());
  79. List<KeyValuePair> assemblies = new List<KeyValuePair>();
  80. foreach (string assembly in InlineFunctionHelper.GetReferencableAssemblies())
  81. {
  82. assemblies.Add(new KeyValuePair(assembly.ToLowerInvariant(), System.IO.Path.GetFileName(assembly)));
  83. }
  84. assemblies.Sort(delegate(KeyValuePair kvp1, KeyValuePair kvp2) { return kvp1.Value.CompareTo(kvp2.Value); });
  85. this.Bindings.Add("Assemblies", assemblies);
  86. List<string> selectedAssemblies =
  87. DataFacade.GetData<IInlineFunctionAssemblyReference>().
  88. Where(f => f.Function == functionInfo.Id).
  89. OrderBy(f => f.Name).
  90. Evaluate().
  91. Select(f => InlineFunctionHelper.GetAssemblyFullPath(f.Name, f.Location).ToLowerInvariant()).
  92. ToList();
  93. this.Bindings.Add("SelectedAssemblies", selectedAssemblies);
  94. List<ManagedParameterDefinition> parameters = ManagedParameterManager.Load(functionInfo.Id).ToList(); ;
  95. this.Bindings.Add("Parameters", parameters);
  96. IEnumerable<Type> popularWidgetTypes = FunctionFacade.WidgetFunctionSupportedTypes.Where(f => f.GetGenericArguments().Any(g => DataFacade.GetAllInterfaces(UserType.Developer).Any(h => h.IsAssignableFrom(g))));
  97. List<Type> parameterTypeOptions = FunctionFacade.FunctionSupportedTypes.Union(popularWidgetTypes).Union(FunctionFacade.WidgetFunctionSupportedTypes).ToList();
  98. this.Bindings.Add("ParameterTypeOptions", parameterTypeOptions);
  99. Guid stateId = Guid.NewGuid();
  100. ParameterEditorState parameterEditorState = new ParameterEditorState { WorkflowId = WorkflowInstanceId };
  101. SessionStateManager.DefaultProvider.AddState<IParameterEditorState>(stateId, parameterEditorState, DateTime.Now.AddDays(7.0));
  102. this.Bindings.Add("SessionStateProvider", SessionStateManager.DefaultProviderName);
  103. this.Bindings.Add("SessionStateId", stateId);
  104. }
  105. private void saveCodeActivity_Save_ExecuteCode(object sender, EventArgs e)
  106. {
  107. IInlineFunction function = this.GetBinding<IInlineFunction>("Function");
  108. string code = this.GetBinding<string>("FunctionCode");
  109. List<string> selectedAssemblies = this.GetBinding<List<string>>("SelectedAssemblies");
  110. using (TransactionScope transactionScope = TransactionsFacade.CreateNewScope())
  111. {
  112. IEnumerable<IInlineFunctionAssemblyReference> assemblyReferences =
  113. DataFacade.GetData<IInlineFunctionAssemblyReference>(f => f.Function == function.Id).Evaluate();
  114. foreach (string selectedAssembly in selectedAssemblies)
  115. {
  116. string name = System.IO.Path.GetFileName(selectedAssembly).ToLowerInvariant();
  117. string location = InlineFunctionHelper.GetAssemblyLocation(selectedAssembly).ToLowerInvariant();
  118. if (assemblyReferences
  119. .Any(f => (string.Compare(f.Name, name, StringComparison.InvariantCultureIgnoreCase) == 0)
  120. && (string.Compare(f.Location, location, StringComparison.InvariantCultureIgnoreCase) == 0)) == false)
  121. {
  122. IInlineFunctionAssemblyReference assemblyReference = DataFacade.BuildNew<IInlineFunctionAssemblyReference>();
  123. assemblyReference.Id = Guid.NewGuid();
  124. assemblyReference.Function = function.Id;
  125. assemblyReference.Name = name;
  126. assemblyReference.Location = location;
  127. DataFacade.AddNew(assemblyReference);
  128. }
  129. }
  130. foreach (IInlineFunctionAssemblyReference assemblyReference in assemblyReferences)
  131. {
  132. string fullPath = InlineFunctionHelper.GetAssemblyFullPath(assemblyReference.Name, assemblyReference.Location);
  133. if (selectedAssemblies.Any(f => string.Compare(f, fullPath, StringComparison.InvariantCultureIgnoreCase) == 0) == false)
  134. {
  135. DataFacade.Delete(assemblyReference);
  136. }
  137. }
  138. IInlineFunction oldFunction = DataFacade.GetData<IInlineFunction>(f => f.Id == function.Id).Single();
  139. if ((oldFunction.Name != function.Name) || (oldFunction.Namespace != function.Namespace))
  140. {
  141. InlineFunctionHelper.FunctionRenamed(function, oldFunction);
  142. }
  143. List<ManagedParameterDefinition> parameters = this.GetBinding<List<ManagedParameterDefinition>>("Parameters");
  144. ManagedParameterManager.Save(function.Id, parameters);
  145. DataFacade.Update(function);
  146. InlineFunctionHelper.SetFunctinoCode(function, code);
  147. transactionScope.Complete();
  148. }
  149. SetSaveStatus(true);
  150. UpdateTreeRefresher updateTreeRefresher = this.CreateUpdateTreeRefresher(this.EntityToken);
  151. updateTreeRefresher.PostRefreshMesseges(function.GetDataEntityToken());
  152. }
  153. private void editCodeActivity_Preview_ExecuteCode(object sender, EventArgs e)
  154. {
  155. IInlineFunction functionInfo = this.GetBinding<IInlineFunction>("Function");
  156. string code = this.GetBinding<string>("FunctionCode");
  157. List<string> selectedAssemblies = this.GetBinding<List<string>>("SelectedAssemblies");
  158. StringInlineFunctionCreateMethodErrorHandler handler = new StringInlineFunctionCreateMethodErrorHandler();
  159. MethodInfo methodInfo = InlineFunctionHelper.Create(functionInfo, code, handler, selectedAssemblies);
  160. FlowControllerServicesContainer serviceContainer = WorkflowFacade.GetFlowControllerServicesContainer(WorkflowEnvironment.WorkflowInstanceId);
  161. IFormFlowWebRenderingService formFlowWebRenderingService = serviceContainer.GetService<IFormFlowWebRenderingService>();
  162. if (handler.HasErrors)
  163. {
  164. StringBuilder sb = new StringBuilder();
  165. if (!string.IsNullOrWhiteSpace(handler.MissingContainerType))
  166. {
  167. AddFormattedTextBlock(sb, handler.MissingContainerType);
  168. }
  169. if (!string.IsNullOrWhiteSpace(handler.NamespaceMismatch))
  170. {
  171. AddFormattedTextBlock(sb, handler.NamespaceMismatch);
  172. }
  173. if (!string.IsNullOrWhiteSpace(handler.MissionMethod))
  174. {
  175. AddFormattedTextBlock(sb, handler.MissionMethod);
  176. }
  177. if (handler.LoadingException != null)
  178. {
  179. AddFormattedTextBlock(sb, handler.LoadingException.ToString());
  180. }
  181. foreach (Tuple<int, string, string> compileError in handler.CompileErrors)
  182. {
  183. AddFormattedTextBlock(sb, "{0} : {1} : {2}".FormatWith(compileError.Item1, compileError.Item2, compileError.Item3));
  184. }
  185. formFlowWebRenderingService.SetNewPageOutput(new LiteralControl(sb.ToString()));
  186. return;
  187. }
  188. List<ManagedParameterDefinition> parameters = this.GetBinding<List<ManagedParameterDefinition>>("Parameters");
  189. List<object> parameterValues = new List<object>();
  190. bool parameterErrors = false;
  191. StringBuilder parameterErrorMessages = new StringBuilder();
  192. foreach (ParameterInfo parameterInfo in methodInfo.GetParameters())
  193. {
  194. ManagedParameterDefinition parameter = parameters.FirstOrDefault(f => f.Name == parameterInfo.Name);
  195. if (parameter == null)
  196. {
  197. string message = string.Format(GetText("CSharpInlineFunction.MissingParameterDefinition"), parameterInfo.Name);
  198. parameterErrors = true;
  199. AddFormattedTextBlock(parameterErrorMessages, message);
  200. }
  201. else if (parameter.Type != parameterInfo.ParameterType)
  202. {
  203. string message = string.Format(GetText("CSharpInlineFunction.WrongParameterTestValueType"), parameterInfo.Name, parameterInfo.ParameterType, parameter.Type);
  204. parameterErrors = true;
  205. AddFormattedTextBlock(parameterErrorMessages, message);
  206. }
  207. else
  208. {
  209. string previewValueFunctionMarkup = (string.IsNullOrEmpty(parameter.TestValueFunctionMarkup) ? parameter.DefaultValueFunctionMarkup : parameter.TestValueFunctionMarkup);
  210. if (string.IsNullOrEmpty(previewValueFunctionMarkup))
  211. {
  212. string message = string.Format(GetText("CSharpInlineFunction.MissingParameterTestOrDefaultValue"), parameterInfo.Name, parameterInfo.ParameterType, parameter.Type);
  213. parameterErrors = true;
  214. AddFormattedTextBlock(parameterErrorMessages, message);
  215. }
  216. else
  217. {
  218. try
  219. {
  220. BaseRuntimeTreeNode treeNode = FunctionFacade.BuildTree(XElement.Parse(previewValueFunctionMarkup));
  221. object value = treeNode.GetValue();
  222. object typedValue = ValueTypeConverter.Convert(value, parameter.Type);
  223. parameterValues.Add(typedValue);
  224. }
  225. catch (Exception ex)
  226. {
  227. string message = string.Format("Error setting '{0}'. {1}", parameterInfo.Name, ex.Message);
  228. parameterErrors = true;
  229. AddFormattedTextBlock(parameterErrorMessages, message);
  230. }
  231. }
  232. }
  233. }
  234. if (parameterErrors)
  235. {
  236. formFlowWebRenderingService.SetNewPageOutput(new LiteralControl(parameterErrorMessages.ToString()));
  237. return;
  238. }
  239. CultureInfo oldCurrentCulture = Thread.CurrentThread.CurrentCulture;
  240. CultureInfo oldCurrentUICulture = Thread.CurrentThread.CurrentUICulture;
  241. try
  242. {
  243. Guid pageId;
  244. if (this.GetBinding<object>("PageId") == null)
  245. {
  246. pageId = Guid.Empty;
  247. }
  248. else
  249. {
  250. pageId = this.GetBinding<Guid>("PageId");
  251. }
  252. string dataScopeName = this.GetBinding<string>("PageDataScopeName");
  253. string cultureName = this.GetBinding<string>("ActiveCultureName");
  254. CultureInfo cultureInfo = null;
  255. if (cultureName != null)
  256. {
  257. cultureInfo = CultureInfo.CreateSpecificCulture(cultureName);
  258. }
  259. using (new DataScope(DataScopeIdentifier.Deserialize(dataScopeName), cultureInfo))
  260. {
  261. Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = cultureInfo;
  262. IPage page = DataFacade.GetData<IPage>(f => f.Id == pageId).FirstOrDefault();
  263. if (page != null)
  264. {
  265. PageRenderer.CurrentPage = page;
  266. }
  267. object result = methodInfo.Invoke(null, parameterValues.ToArray());
  268. string resultString;
  269. try
  270. {
  271. resultString = PrettyPrinter.Print(result);
  272. }
  273. catch(Exception ex)
  274. {
  275. throw new TargetInvocationException(ex);
  276. }
  277. SetOutput(formFlowWebRenderingService, resultString);
  278. }
  279. }
  280. catch (TargetInvocationException ex)
  281. {
  282. SetOutput(formFlowWebRenderingService, ex.InnerException.ToString());
  283. }
  284. finally
  285. {
  286. Thread.CurrentThread.CurrentCulture = oldCurrentCulture;
  287. Thread.CurrentThread.CurrentUICulture = oldCurrentUICulture;
  288. }
  289. }
  290. private void AddFormattedTextBlock(StringBuilder sb, string text) {
  291. sb.Append("<pre>");
  292. sb.Append(HttpUtility.HtmlEncode(text));
  293. sb.AppendLine("</pre>");
  294. }
  295. private void SetOutput(IFormFlowWebRenderingService formFlowWebRenderingService, string text)
  296. {
  297. Control output = new LiteralControl("<pre>" + HttpUtility.HtmlEncode(text) + "</pre>");
  298. formFlowWebRenderingService.SetNewPageOutput(output);
  299. }
  300. private string GetText(string key)
  301. {
  302. return StringResourceSystemFacade.GetString("Composite.Plugins.MethodBasedFunctionProviderElementProvider", key);
  303. }
  304. }
  305. [Serializable]
  306. public sealed class ParameterEditorState : IParameterEditorState
  307. {
  308. public Guid WorkflowId { get; set; }
  309. private FormData GetFormData()
  310. {
  311. return WorkflowFacade.GetFormData(WorkflowId);
  312. }
  313. [XmlIgnore]
  314. public List<ManagedParameterDefinition> Parameters
  315. {
  316. get { return GetFormData().Bindings["Parameters"] as List<ManagedParameterDefinition>; }
  317. set { GetFormData().Bindings["Parameters"] = value; }
  318. }
  319. [XmlIgnore]
  320. public List<Type> ParameterTypeOptions
  321. {
  322. get { return (GetFormData().Bindings["ParameterTypeOptions"] as IEnumerable<Type>).ToList(); }
  323. set { GetFormData().Bindings["ParameterTypeOptions"] = value.ToList(); }
  324. }
  325. }
  326. }