diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f07a33b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,278 @@ +############################### +# Core EditorConfig Options # +############################### + +root=true + +# All files +[*] +indent_style=space +trim_trailing_whitespace=true + +# Code files +[*.{asax,ascx,aspx,cs,csx,cshtml,css,htm,html,js,json,jsx,master,razor,resjson,skin,ts,tsx,vb,vbx}] +indent_size=4 +insert_final_newline=true +charset=utf-8-bom + +# Xml files +[*.{appxmanifest,build,config,csproj,dbml,discomap,dtd,jsproj,lsproj,njsproj,nuspec,proj,props,resw,resx,StyleCop,targets,tasks,vbproj,xaml,xamlx,xml,xoml,xsd}] +indent_size=2 +tab_width=2 + +############################### +# .NET Coding Conventions # +############################### + +[*.{cs,vb}] +# Organize usings +dotnet_sort_system_directives_first=true +dotnet_separate_import_directive_groups=false + +# this. preferences +dotnet_style_qualification_for_field=false:hint +dotnet_style_qualification_for_property=false:hint +dotnet_style_qualification_for_method=false:hint +dotnet_style_qualification_for_event=false:hint + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members=true:hint +dotnet_style_predefined_type_for_member_access=false:hint + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators=always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators=always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators=always_for_clarity:silent +dotnet_style_parentheses_in_other_operators=never_if_unnecessary:silent + +# Modifier preferences +dotnet_style_require_accessibility_modifiers=for_non_interface_members:hint +dotnet_style_readonly_field=true:suggestion + +# Expression-level preferences +dotnet_style_object_initializer=true:suggestion +dotnet_style_collection_initializer=true:suggestion +dotnet_style_explicit_tuple_names=true:suggestion +dotnet_style_null_propagation=true:suggestion +dotnet_style_coalesce_expression=true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method=true:silent +dotnet_style_prefer_inferred_tuple_names=true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names=true:suggestion +dotnet_style_prefer_auto_properties=true:silent +dotnet_style_prefer_conditional_expression_over_assignment=true:silent +dotnet_style_prefer_conditional_expression_over_return=true:silent +dotnet_style_prefer_compound_assignment=true:suggestion + +############################### +# Naming Conventions # +############################### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity=suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols=interface +dotnet_naming_rule.interface_should_be_begins_with_i.style=begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity=suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols=types +dotnet_naming_rule.types_should_be_pascal_case.style=pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity=suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols=non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style=pascal_case + +dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.severity=suggestion +dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.symbols=private_or_internal_field +dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.style=begins_with__ + +dotnet_naming_rule.private_or_internal_static_field_should_be_begins_with__.severity=suggestion +dotnet_naming_rule.private_or_internal_static_field_should_be_begins_with__.symbols=private_or_internal_static_field +dotnet_naming_rule.private_or_internal_static_field_should_be_begins_with__.style=begins_with__ + +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity=suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols=constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style=pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds=interface +dotnet_naming_symbols.interface.applicable_accessibilities=public, internal, private, protected, protected_internal +dotnet_naming_symbols.interface.required_modifiers= + +dotnet_naming_symbols.private_or_internal_field.applicable_kinds=field +dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities=internal, private +dotnet_naming_symbols.private_or_internal_field.required_modifiers= + +dotnet_naming_symbols.private_or_internal_static_field.applicable_kinds=field +dotnet_naming_symbols.private_or_internal_static_field.applicable_accessibilities=internal, private +dotnet_naming_symbols.private_or_internal_static_field.required_modifiers=static + +dotnet_naming_symbols.types.applicable_kinds=class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities=public, internal, private, protected, protected_internal +dotnet_naming_symbols.types.required_modifiers= + +dotnet_naming_symbols.non_field_members.applicable_kinds=property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities=public, internal, private, protected, protected_internal +dotnet_naming_symbols.non_field_members.required_modifiers= + +dotnet_naming_symbols.constant_fields.applicable_kinds=field +dotnet_naming_symbols.constant_fields.applicable_accessibilities=* +dotnet_naming_symbols.constant_fields.required_modifiers=const + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix= +dotnet_naming_style.pascal_case.required_suffix= +dotnet_naming_style.pascal_case.word_separator= +dotnet_naming_style.pascal_case.capitalization=pascal_case + +dotnet_naming_style.begins_with_i.required_prefix=I +dotnet_naming_style.begins_with_i.required_suffix= +dotnet_naming_style.begins_with_i.word_separator= +dotnet_naming_style.begins_with_i.capitalization=pascal_case + +dotnet_naming_style.begins_with__.required_prefix=_ +dotnet_naming_style.begins_with__.required_suffix= +dotnet_naming_style.begins_with__.word_separator= +dotnet_naming_style.begins_with__.capitalization=camel_case + + +############################### +# C# Code Style Rules # +############################### + +[*.cs] +# var preferences +csharp_style_var_for_built_in_types=false:hint +csharp_style_var_when_type_is_apparent=true:hint +csharp_style_var_elsewhere=false:hint + +# Expression-bodied members +csharp_style_expression_bodied_methods=false:silent +csharp_style_expression_bodied_constructors=false:silent +csharp_style_expression_bodied_operators=false:silent +csharp_style_expression_bodied_properties=true:silent +csharp_style_expression_bodied_indexers=true:silent +csharp_style_expression_bodied_accessors=true:silent +csharp_style_expression_bodied_lambdas=true:silent +csharp_style_expression_bodied_local_functions=false:silent + +# Pattern-matching preferences +csharp_style_pattern_matching_over_is_with_cast_check=true:suggestion +csharp_style_pattern_matching_over_as_with_null_check=true:suggestion +csharp_style_prefer_switch_expression=true:suggestion + +# Null-checking preferences +csharp_style_throw_expression=true:suggestion +csharp_style_conditional_delegate_call=true:suggestion + +# Modifier preferences +csharp_prefer_static_local_function=true:suggestion +csharp_preferred_modifier_order=public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion + +# Expression-level preferences +csharp_prefer_braces=true:silent +csharp_style_deconstructed_variable_declaration=true:suggestion +csharp_prefer_simple_default_expression=true:suggestion +csharp_prefer_simple_using_statement=true:suggestion +csharp_style_pattern_local_over_anonymous_function=true:suggestion +csharp_style_inlined_variable_declaration=true:suggestion +csharp_style_prefer_index_operator=true:suggestion +csharp_style_prefer_range_operator=true:suggestion +csharp_style_unused_value_assignment_preference=discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference=discard_variable:silent + +# 'using' directive preferences +csharp_using_directive_placement=outside_namespace:silent + +############################### +# C# Code Quality Rules # +############################### + +# Parameter preferences +dotnet_code_quality_unused_parameters=all:suggestion + +############################### +# C# Formatting Rules # +############################### + +# New line preferences +csharp_new_line_before_open_brace=all +csharp_new_line_before_else=true +csharp_new_line_before_catch=true +csharp_new_line_before_finally=true +csharp_new_line_before_members_in_object_initializers=false +csharp_new_line_before_members_in_anonymous_types=true +csharp_new_line_between_query_expression_clauses=true + +# Indentation preferences +csharp_indent_block_contents=true +csharp_indent_braces=false +csharp_indent_case_contents_when_block=true +csharp_indent_case_contents=true +csharp_indent_switch_labels=true +csharp_indent_labels=flush_left + +# Space preferences +csharp_space_after_cast=false +csharp_space_after_keywords_in_control_flow_statements=true +csharp_space_between_method_call_parameter_list_parentheses=false +csharp_space_between_method_declaration_parameter_list_parentheses=false +csharp_space_between_parentheses=false +csharp_space_before_colon_in_inheritance_clause=true +csharp_space_after_colon_in_inheritance_clause=true +csharp_space_around_binary_operators=before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses=false +csharp_space_between_method_call_name_and_opening_parenthesis=false +csharp_space_between_method_call_empty_parameter_list_parentheses=false +csharp_space_after_comma=true +csharp_space_after_dot=false +csharp_space_after_semicolon_in_for_statement=true +csharp_space_around_declaration_statements=false +csharp_space_before_comma=false +csharp_space_before_dot=false +csharp_space_before_open_square_brackets=false +csharp_space_before_semicolon_in_for_statement=false +csharp_space_between_empty_square_brackets=false +csharp_space_between_method_declaration_name_and_open_parenthesis=false +csharp_space_between_square_brackets=false + +# Wrapping preferences +csharp_preserve_single_line_statements=true +csharp_preserve_single_line_blocks=true + +############################### +# Resharper specifics # +############################### + +# ReSharper properties +resharper_csharp_insert_final_newline=true +resharper_csharp_max_line_length=200 +resharper_csharp_use_indent_from_vs=true +resharper_css_use_indent_from_vs=true +resharper_html_use_indent_from_vs=true +resharper_js_max_line_length=200 +resharper_js_use_indent_from_vs=true +resharper_keep_existing_declaration_block_arrangement=true +resharper_keep_existing_embedded_block_arrangement=false +resharper_keep_existing_enum_arrangement=false +resharper_max_attribute_length_for_same_line=200 +resharper_place_accessorholder_attribute_on_same_line=false +resharper_place_field_attribute_on_same_line=false +resharper_space_within_single_line_array_initializer_braces=true +resharper_xmldoc_max_line_length=200 +resharper_xmldoc_use_indent_from_vs=true +resharper_xml_blank_line_after_pi=false +resharper_xml_max_line_length=200 +resharper_xml_use_indent_from_vs=true + +# ReSharper inspection severities +resharper_comment_typo_highlighting=hint +resharper_identifier_typo_highlighting=hint +resharper_markup_attribute_typo_highlighting=hint +resharper_markup_text_typo_highlighting=hint +resharper_mvc_partial_view_not_resolved_highlighting=warning +resharper_mvc_template_not_resolved_highlighting=hint +resharper_mvc_view_not_resolved_highlighting=warning +resharper_redundant_base_qualifier_highlighting=warning +resharper_string_literal_typo_highlighting=hint diff --git a/Epinova.InRiverConnector.sln b/Epinova.InRiverConnector.sln index ba7a45e..0a25686 100644 --- a/Epinova.InRiverConnector.sln +++ b/Epinova.InRiverConnector.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.15 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29418.71 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EpiserverAdapter", "src\EpiserverAdapter\EpiserverAdapter.csproj", "{F6FC6A0D-D026-4FC3-873C-19AF480821D5}" EndProject @@ -15,6 +15,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EpiserverAdapterTests", "te EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EpiserverRestApi", "EpiserverRestApi\EpiserverRestApi.csproj", "{36C58EE9-57CD-4EC6-A600-F689A8F4B22B}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{7A7A4228-2651-4ADA-8099-0A83CC0B8453}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .gitignore = .gitignore + License.txt = License.txt + README.md = README.md + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Epinova.InRiverConnector.sln.DotSettings b/Epinova.InRiverConnector.sln.DotSettings index 8d8bfed..a7077b6 100644 --- a/Epinova.InRiverConnector.sln.DotSettings +++ b/Epinova.InRiverConnector.sln.DotSettings @@ -1,34 +1,7 @@  - - True - HINT - HINT - HINT - WARNING - HINT - WARNING <?xml version="1.0" encoding="utf-16"?><Profile name="Silent"><AspOptimizeRegisterDirectives>False</AspOptimizeRegisterDirectives><HtmlReformatCode>True</HtmlReformatCode><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSRemoveCodeRedundancies>False</CSRemoveCodeRedundancies><CSUseAutoProperty>False</CSUseAutoProperty><CSMakeFieldReadonly>False</CSMakeFieldReadonly><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSUpdateFileHeader>False</CSUpdateFileHeader><VBOptimizeImports>True</VBOptimizeImports><VBShortenReferences>True</VBShortenReferences><JsInsertSemicolon>True</JsInsertSemicolon><JsReformatCode>True</JsReformatCode><CssReformatCode>True</CssReformatCode><XMLReformatCode>True</XMLReformatCode><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName /></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><VBReformatCode>True</VBReformatCode><CSReformatCode>True</CSReformatCode><CSReorderTypeMembers>True</CSReorderTypeMembers><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="False" RemoveRedundantParentheses="False" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" ArrangeCodeBodyStyle="False" ArrangeVarStyle="True" /></Profile> - Silent Silent - UseClrName - 200 - NEVER - False - NEVER - True - False - 200 - False - False - False - 200 - False - 200 False - 2 - 2 - False - 200 <?xml version="1.0" encoding="utf-16"?> <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns"> <TypePattern Priority="0" DisplayName="COM interfaces or structs"> @@ -45,160 +18,8 @@ </Or> </TypePattern.Match> </TypePattern> - <TypePattern Priority="0" DisplayName="NUnit Test Fixtures" RemoveRegions="AllExceptGenerated"> - <TypePattern.Match> - <And> - <Kind Is="Class" /> - <Or> - <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TestCaseFixtureAttribute" Inherited="True" /> - </Or> - </And> - </TypePattern.Match> - <Entry DisplayName="Static Fields and Constants"> - <Entry.Match> - <Or> - <Kind Is="Constant" /> - <And> - <Kind Is="Field" /> - <Static /> - </And> - </Or> - </Entry.Match> - <Entry.SortBy> - <Kind Is="Member" /> - <Name Is="Enter Pattern Here" /> - </Entry.SortBy> - </Entry> - <Entry DisplayName="Public Delegates" Priority="100"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Delegate" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - <Entry DisplayName="Public Enums" Priority="100"> - <Entry.Match> - <And> - <Access Is="Public" /> - <Kind Is="Enum" /> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - <Entry DisplayName="Fields"> - <Entry.Match> - <And> - <Kind Is="Field" /> - <Not> - <Static /> - </Not> - </And> - </Entry.Match> - <Entry.SortBy> - <Readonly /> - <Name /> - </Entry.SortBy> - </Entry> - <Entry DisplayName="Constructors"> - <Entry.Match> - <Kind Is="Constructor" /> - </Entry.Match> - <Entry.SortBy> - <Static /> - </Entry.SortBy> - </Entry> - <Entry DisplayName="Properties, Indexers" Priority="100"> - <Entry.Match> - <Or> - <Kind Is="Property" /> - <Kind Is="Indexer" /> - </Or> - </Entry.Match> - <Entry.SortBy> - <Static /> - <Access /> - <Name Is="Enter Pattern Here" /> - </Entry.SortBy> - </Entry> - <Entry DisplayName="Interface Implementations" Priority="100"> - <Entry.Match> - <And> - <Kind Is="Member" /> - <ImplementsInterface /> - </And> - </Entry.Match> - <Entry.SortBy> - <ImplementsInterface Name="IDisposable" /> - <Name Is="Enter Pattern Here" /> - </Entry.SortBy> - </Entry> - <Region Name="Setup/Teardown"> - <Entry DisplayName="Setup/Teardown Methods" Priority="100"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TestFixtureSetUpAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.TestFixtureTearDownAttribute" Inherited="True" /> - <HasAttribute Name="NUnit.Framework.OneTimeSetUpAttribute" /> - <HasAttribute Name="NUnit.Framework.OneTimeTearDownAttribute" /> - </Or> - </And> - </Entry.Match> - <Entry.SortBy> - <Name Is="Enter Pattern Here" /> - </Entry.SortBy> - </Entry> - </Region> - <Entry DisplayName="Test Methods"> - <Entry.Match> - <And> - <Kind Is="Method" /> - <Or> - <HasAttribute Name="NUnit.Framework.TestAttribute" /> - <HasAttribute Name="NUnit.Framework.TestCaseAttribute" /> - </Or> - </And> - </Entry.Match> - <Entry.SortBy> - <Name /> - </Entry.SortBy> - </Entry> - <Entry DisplayName="All other members"> - <Entry.SortBy> - <Access /> - <Static /> - <Virtual /> - <Name Is="Enter Pattern Here" /> - </Entry.SortBy> - </Entry> - <Region Name="Nested type: ${0}"> - <Region.GroupBy> - <Name Is="Enter Pattern Here" /> - </Region.GroupBy> - <Entry DisplayName="Nested Types"> - <Entry.Match> - <Kind Is="Type" /> - </Entry.Match> - <Entry.SortBy> - <Name Is="Enter Pattern Here" /> - </Entry.SortBy> - </Entry> - </Region> - </TypePattern> <TypePattern Priority="0" DisplayName="Default Pattern" RemoveRegions="AllExceptGenerated"> - <Entry DisplayName="Public Delegates" Priority="100"> + <Entry Priority="100" DisplayName="Public Delegates"> <Entry.Match> <And> <Access Is="Public" /> @@ -209,7 +30,7 @@ <Name /> </Entry.SortBy> </Entry> - <Entry DisplayName="Public Enums" Priority="100"> + <Entry Priority="100" DisplayName="Public Enums"> <Entry.Match> <And> <Access Is="Public" /> @@ -257,7 +78,7 @@ <Static /> </Entry.SortBy> </Entry> - <Entry DisplayName="Properties, Indexers" Priority="100"> + <Entry Priority="100" DisplayName="Properties, Indexers"> <Entry.Match> <Or> <Kind Is="Property" /> @@ -270,7 +91,7 @@ <Name Is="Enter Pattern Here" /> </Entry.SortBy> </Entry> - <Entry DisplayName="Interface Implementations" Priority="100"> + <Entry Priority="100" DisplayName="Interface Implementations"> <Entry.Match> <And> <Kind Is="Member" /> @@ -290,38 +111,20 @@ <Name Is="Enter Pattern Here" /> </Entry.SortBy> </Entry> - <Region Name="Nested type: ${0}"> - <Region.GroupBy> + <Entry DisplayName="Nested Types"> + <Entry.Match> + <Kind Is="Type" /> + </Entry.Match> + <Entry.SortBy> <Name Is="Enter Pattern Here" /> - </Region.GroupBy> - <Entry DisplayName="Nested Types"> - <Entry.Match> - <Kind Is="Type" /> - </Entry.Match> - <Entry.SortBy> - <Name Is="Enter Pattern Here" /> - </Entry.SortBy> - </Entry> - </Region> + </Entry.SortBy> + </Entry> </TypePattern> </Patterns> - UseVarWhenEvident - UseVarWhenEvident - UseVarWhenEvident - ID - UI - True - True - True - True - True - True + <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> True - True - True - True - True - True - True Integration, Manual - True \ No newline at end of file + True + True + diff --git a/EpiserverRestApi/App_Start/FilterConfig.cs b/EpiserverRestApi/App_Start/FilterConfig.cs index 220f990..2dde5ad 100644 --- a/EpiserverRestApi/App_Start/FilterConfig.cs +++ b/EpiserverRestApi/App_Start/FilterConfig.cs @@ -1,5 +1,4 @@ -using System.Web; -using System.Web.Mvc; +using System.Web.Mvc; namespace EpiserverRestApi { diff --git a/EpiserverRestApi/App_Start/RouteConfig.cs b/EpiserverRestApi/App_Start/RouteConfig.cs index 24dd621..af409fd 100644 --- a/EpiserverRestApi/App_Start/RouteConfig.cs +++ b/EpiserverRestApi/App_Start/RouteConfig.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Mvc; +using System.Web.Mvc; using System.Web.Routing; namespace EpiserverRestApi diff --git a/EpiserverRestApi/App_Start/WebApiConfig.cs b/EpiserverRestApi/App_Start/WebApiConfig.cs index 1b043af..6a9d193 100644 --- a/EpiserverRestApi/App_Start/WebApiConfig.cs +++ b/EpiserverRestApi/App_Start/WebApiConfig.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web.Http; +using System.Web.Http; namespace EpiserverRestApi { diff --git a/EpiserverRestApi/ChannelDataController.cs b/EpiserverRestApi/ChannelDataController.cs index a0fb9fd..274e62d 100644 --- a/EpiserverRestApi/ChannelDataController.cs +++ b/EpiserverRestApi/ChannelDataController.cs @@ -16,9 +16,9 @@ public class ChannelDataController : ApiController [Route("GetVariations/{nodeName}")] public IEnumerable GetVariations(string nodeName) { - authenticate(); + Authenticate(); - int channelId = int.Parse(ConfigurationManager.AppSettings["channelId"]); + int channelId = Int32.Parse(ConfigurationManager.AppSettings["channelId"]); Entity node = RemoteManager.ChannelService.GetEntitiesForChannelAndEntityType(channelId, "ChannelNode") .FirstOrDefault(x => x.DisplayName.Data.ToString().Equals(nodeName, StringComparison.InvariantCultureIgnoreCase)); if (node == null) @@ -28,12 +28,13 @@ public IEnumerable GetVariations(string nodeName) .Select(x => x.Name); } - private void authenticate() + private static void Authenticate() { - AuthenticationTicket ticket = RemoteManager.Authenticate(ConfigurationManager.AppSettings["authenticationUrl"], ConfigurationManager.AppSettings["username"], ConfigurationManager.AppSettings["password"]); + AuthenticationTicket ticket = RemoteManager.Authenticate(ConfigurationManager.AppSettings["authenticationUrl"], ConfigurationManager.AppSettings["username"], + ConfigurationManager.AppSettings["password"]); // Initialize RemoteManager RemoteManager.CreateInstance(ConfigurationManager.AppSettings["authenticationUrl"], ticket); } } -} \ No newline at end of file +} diff --git a/EpiserverRestApi/EpiserverRestApi.csproj b/EpiserverRestApi/EpiserverRestApi.csproj index 3834395..88dffab 100644 --- a/EpiserverRestApi/EpiserverRestApi.csproj +++ b/EpiserverRestApi/EpiserverRestApi.csproj @@ -1,6 +1,6 @@  - + Debug @@ -23,8 +23,6 @@ - - true @@ -49,9 +47,12 @@ False ..\lib\inRiver.Remoting.dll + + ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll + - - ..\packages\structuremap.web.4.0.0.315\lib\net40\StructureMap.Web.dll + + ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll @@ -64,12 +65,15 @@ + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + ..\packages\System.Security.AccessControl.4.4.0\lib\net461\System.Security.AccessControl.dll - - ..\packages\System.Security.Cryptography.Xml.4.4.0\lib\net461\System.Security.Cryptography.Xml.dll + + ..\packages\System.Security.Cryptography.Xml.4.4.2\lib\net461\System.Security.Cryptography.Xml.dll ..\packages\System.Security.Permissions.4.4.0\lib\net461\System.Security.Permissions.dll @@ -86,6 +90,30 @@ + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll + + + ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll + + + ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll + + + ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll + + + ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll + @@ -97,49 +125,13 @@ True ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll - - - ..\packages\Microsoft.AspNet.WebApi.Client.5.2.4\lib\net45\System.Net.Http.Formatting.dll - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.Helpers.dll - - - ..\packages\Microsoft.AspNet.WebApi.Core.5.2.4\lib\net45\System.Web.Http.dll - - - ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.4\lib\net45\System.Web.Http.WebHost.dll - - - True - ..\packages\Microsoft.AspNet.Mvc.5.2.4\lib\net45\System.Web.Mvc.dll - ..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll - - True - ..\packages\Microsoft.AspNet.Razor.3.2.4\lib\net45\System.Web.Razor.dll - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.WebPages.dll - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.WebPages.Deployment.dll - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.WebPages.Razor.dll - True ..\packages\WebGrease.1.6.0\lib\WebGrease.dll @@ -149,11 +141,6 @@ ..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll - - - ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll - - @@ -167,7 +154,9 @@ - + + Designer + Web.config @@ -175,9 +164,7 @@ Web.config - - - + @@ -215,16 +202,4 @@ - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file diff --git a/EpiserverRestApi/Global.asax.cs b/EpiserverRestApi/Global.asax.cs index bdf5864..0720ba7 100644 --- a/EpiserverRestApi/Global.asax.cs +++ b/EpiserverRestApi/Global.asax.cs @@ -1,24 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; +using System.Web; using System.Web.Http; -using System.Web.Mvc; -using System.Web.Optimization; using System.Web.Routing; namespace EpiserverRestApi { - public class WebApiApplication : System.Web.HttpApplication + public class WebApiApplication : HttpApplication { protected void Application_Start() { - GlobalConfiguration.Configure(WebApiConfig.Register); - + RouteConfig.RegisterRoutes(RouteTable.Routes); - } - } } diff --git a/EpiserverRestApi/Properties/AssemblyInfo.cs b/EpiserverRestApi/Properties/AssemblyInfo.cs index c5b91ee..f6c64fe 100644 --- a/EpiserverRestApi/Properties/AssemblyInfo.cs +++ b/EpiserverRestApi/Properties/AssemblyInfo.cs @@ -1,10 +1,6 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. [assembly: AssemblyTitle("EpiserverRestApi")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] @@ -13,23 +9,7 @@ [assembly: AssemblyCopyright("Copyright © 2019")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("9335fc88-0142-4f65-bd11-dcfad7f7fbe3")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("1.4.0.0")] +[assembly: AssemblyFileVersion("1.4.0.0")] diff --git a/EpiserverRestApi/Web.Debug.config b/EpiserverRestApi/Web.Debug.config index d7712aa..5d488d4 100644 --- a/EpiserverRestApi/Web.Debug.config +++ b/EpiserverRestApi/Web.Debug.config @@ -27,4 +27,4 @@ --> - + \ No newline at end of file diff --git a/EpiserverRestApi/Web.Release.config b/EpiserverRestApi/Web.Release.config index 28a4d5f..602152c 100644 --- a/EpiserverRestApi/Web.Release.config +++ b/EpiserverRestApi/Web.Release.config @@ -28,4 +28,4 @@ --> - + \ No newline at end of file diff --git a/EpiserverRestApi/Web.config b/EpiserverRestApi/Web.config index 48861b3..754f835 100644 --- a/EpiserverRestApi/Web.config +++ b/EpiserverRestApi/Web.config @@ -9,10 +9,10 @@ - - - - + + + + @@ -23,7 +23,8 @@ - + @@ -34,7 +35,7 @@ - + @@ -44,18 +45,6 @@ - - - - - - - - - - - - @@ -90,18 +79,35 @@ - + - + + + + + + + + + + + + + - - + + \ No newline at end of file diff --git a/EpiserverRestApi/packages.config b/EpiserverRestApi/packages.config index 806b934..4bd7f07 100644 --- a/EpiserverRestApi/packages.config +++ b/EpiserverRestApi/packages.config @@ -1,26 +1,25 @@  - - + + - - - - - - - + + + + + + + - - + - + diff --git a/EpiserverRestApi/test.txt b/EpiserverRestApi/test.txt deleted file mode 100644 index 30d74d2..0000000 --- a/EpiserverRestApi/test.txt +++ /dev/null @@ -1 +0,0 @@ -test \ No newline at end of file diff --git a/lib/Newtonsoft.Json.dll b/lib/Newtonsoft.Json.dll deleted file mode 100644 index b7ef414..0000000 Binary files a/lib/Newtonsoft.Json.dll and /dev/null differ diff --git a/lib/System.Net.Http.Formatting.dll b/lib/System.Net.Http.Formatting.dll deleted file mode 100644 index 3b76acd..0000000 Binary files a/lib/System.Net.Http.Formatting.dll and /dev/null differ diff --git a/lib/System.Web.Http.WebHost.dll b/lib/System.Web.Http.WebHost.dll deleted file mode 100644 index 4f2b581..0000000 Binary files a/lib/System.Web.Http.WebHost.dll and /dev/null differ diff --git a/lib/System.Web.Http.dll b/lib/System.Web.Http.dll deleted file mode 100644 index e1dbdd1..0000000 Binary files a/lib/System.Web.Http.dll and /dev/null differ diff --git a/src/EpiserverAdapter/AsyncHelper.cs b/src/EpiserverAdapter/AsyncHelper.cs new file mode 100644 index 0000000..eb14a9a --- /dev/null +++ b/src/EpiserverAdapter/AsyncHelper.cs @@ -0,0 +1,29 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Epinova.InRiverConnector.EpiserverAdapter +{ + internal static class AsyncHelper + { + private static readonly TaskFactory TaskFactory = new + TaskFactory(CancellationToken.None, + TaskCreationOptions.None, + TaskContinuationOptions.None, + TaskScheduler.Default); + + public static TResult RunSync(Func> func) + => TaskFactory + .StartNew(func) + .Unwrap() + .GetAwaiter() + .GetResult(); + + public static void RunSync(Func func) + => TaskFactory + .StartNew(func) + .Unwrap() + .GetAwaiter() + .GetResult(); + } +} diff --git a/src/EpiserverAdapter/CatalogCodeGenerator.cs b/src/EpiserverAdapter/CatalogCodeGenerator.cs index 92f6f52..4aba9ed 100644 --- a/src/EpiserverAdapter/CatalogCodeGenerator.cs +++ b/src/EpiserverAdapter/CatalogCodeGenerator.cs @@ -14,12 +14,17 @@ public CatalogCodeGenerator(IConfiguration config, IEntityService entityService) _entityService = entityService; } + public string GetAssociationKey(string entityCode, string parentCode, string associationName) + { + return $"{entityCode}_{parentCode}_{associationName}"; + } + public string GetEpiserverCode(int entityId) { if (entityId == 0) return null; - var entity = _entityService.GetEntity(entityId, LoadLevel.DataOnly); + Entity entity = _entityService.GetEntity(entityId, LoadLevel.DataOnly); return GetEpiserverCode(entity); } @@ -33,12 +38,12 @@ public string GetEpiserverCode(Entity entity) if (entity.LoadLevel < LoadLevel.DataOnly) entity = _entityService.GetEntity(entity.Id, LoadLevel.DataOnly); - var entityTypeId = entity.EntityType.Id; - + string entityTypeId = entity.EntityType.Id; + if (_config.EpiCodeMapping.ContainsKey(entityTypeId)) { - var mappedCodeFieldId = _config.EpiCodeMapping[entityTypeId]; - var mappedCodeField = entity.Fields.FirstOrDefault(x => x.FieldType.Id == mappedCodeFieldId); + string mappedCodeFieldId = _config.EpiCodeMapping[entityTypeId]; + Field mappedCodeField = entity.Fields.FirstOrDefault(x => x.FieldType.Id == mappedCodeFieldId); if (mappedCodeField != null) return GetPrefixedValue(mappedCodeField.Data); } @@ -46,6 +51,11 @@ public string GetEpiserverCode(Entity entity) return GetPrefixedValue(entity.Id); } + public string GetPrefixedCode(string skuCode) + { + return GetPrefixedValue(skuCode); + } + public string GetRelationName(string skuId, string parentCode) { return $"{_config.ChannelIdPrefix}_{skuId}_{parentCode}"; @@ -56,19 +66,9 @@ public string GetRelationName(int entityId, int parentEntityId) return $"{_config.ChannelIdPrefix}_{entityId}_{parentEntityId}"; } - public string GetPrefixedCode(string skuCode) - { - return GetPrefixedValue(skuCode); - } - private string GetPrefixedValue(object data) { return $"{_config.ChannelIdPrefix}{data}"; } - - public string GetAssociationKey(string entityCode, string parentCode, string associationName) - { - return $"{entityCode}_{parentCode}_{associationName}"; - } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/CatalogElementContainer.cs b/src/EpiserverAdapter/CatalogElementContainer.cs index a0febc5..53d59ca 100644 --- a/src/EpiserverAdapter/CatalogElementContainer.cs +++ b/src/EpiserverAdapter/CatalogElementContainer.cs @@ -5,6 +5,11 @@ namespace Epinova.InRiverConnector.EpiserverAdapter { public class CatalogElementContainer { + private readonly List _addedAssociations; + private readonly List _addedEntities; + private readonly List _addedNodes; + private readonly List _addedRelations; + public CatalogElementContainer() { Nodes = new List(); @@ -18,25 +23,20 @@ public CatalogElementContainer() _addedAssociations = new List(); } - private readonly List _addedEntities; - private readonly List _addedNodes; - private readonly List _addedRelations; - private readonly List _addedAssociations; - - public List Nodes { get; } + public List Associations { get; set; } public List Entries { get; } + public List Nodes { get; } public List Relations { get; set; } - public List Associations { get; set; } - public void AddRelation(XElement relation, string relationName) + public void AddAssociation(XElement association, string associationKey) { - Relations.Add(relation); - _addedRelations.Add(relationName); + Associations.Add(association); + _addedAssociations.Add(associationKey); } - public bool HasRelation(string relationName) + public void AddAssociationKey(string associationKey) { - return _addedRelations.Contains(relationName); + _addedAssociations.Add(associationKey); } public void AddEntry(XElement entry, string entryCode) @@ -45,36 +45,36 @@ public void AddEntry(XElement entry, string entryCode) _addedEntities.Add(entryCode); } - public bool HasEntry(string entryCode) - { - return _addedEntities.Contains(entryCode); - } - public void AddNode(XElement node, string nodeCode) { Nodes.Add(node); _addedNodes.Add(nodeCode); } - public bool HasNode(string nodeCode) + public void AddRelation(XElement relation, string relationName) { - return _addedNodes.Contains(nodeCode); + Relations.Add(relation); + _addedRelations.Add(relationName); } - public void AddAssociationKey(string associationKey) + public bool HasAssociation(string associationKey) { - _addedAssociations.Add(associationKey); + return _addedAssociations.Contains(associationKey); } - public void AddAssociation(XElement association, string associationKey) + public bool HasEntry(string entryCode) { - Associations.Add(association); - _addedAssociations.Add(associationKey); + return _addedEntities.Contains(entryCode); } - public bool HasAssociation(string associationKey) + public bool HasNode(string nodeCode) { - return _addedAssociations.Contains(associationKey); + return _addedNodes.Contains(nodeCode); + } + + public bool HasRelation(string relationName) + { + return _addedRelations.Contains(relationName); } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/ChannelPublisher.cs b/src/EpiserverAdapter/ChannelPublisher.cs index 602448b..11d3e81 100644 --- a/src/EpiserverAdapter/ChannelPublisher.cs +++ b/src/EpiserverAdapter/ChannelPublisher.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; using System.Xml.Linq; using Epinova.InRiverConnector.EpiserverAdapter.Communication; using Epinova.InRiverConnector.EpiserverAdapter.Helpers; @@ -52,7 +53,7 @@ public ChannelPublisher(IConfiguration config, _catalogCodeGenerator = catalogCodeGenerator; } - public ConnectorEvent ChannelEntityAdded(Entity channel, int entityId) + public async Task ChannelEntityAddedAsync(Entity channel, int entityId) { ConnectorEvent connectorEvent = ConnectorEventHelper.InitiateEvent(_config, ConnectorEventType.ChannelEntityAdded, $"Received entity added for entity {entityId} in channel {channel.DisplayName}", 0); @@ -79,28 +80,28 @@ public ConnectorEvent ChannelEntityAdded(Entity channel, int entityId) structureEntities.AddRange(childLinks); - PublishEntities(channel, connectorEvent, structureEntities); + await PublishEntitiesAsync(channel, connectorEvent, structureEntities); string channelName = _mappingHelper.GetNameForEntity(channel, 100); - _epiApi.ImportUpdateCompleted(channelName, ImportUpdateCompletedEventType.EntityAdded, true); + await _epiApi.ImportUpdateCompletedAsync(channelName, ImportUpdateCompletedEventType.EntityAdded, true); return connectorEvent; } - public ConnectorEvent ChannelEntityDeleted(Entity channel, Entity deletedEntity) + public async Task ChannelEntityDeletedAsync(Entity channel, Entity deletedEntity) { string channelName = _mappingHelper.GetNameForEntity(channel, 100); ConnectorEvent connectorEvent = ConnectorEventHelper.InitiateEvent(_config, ConnectorEventType.ChannelEntityDeleted, $"Received entity deleted for entity {deletedEntity.Id} in channel {channelName}.", 0); - Delete(channel, deletedEntity); + await DeleteAsync(channel, deletedEntity); - _epiApi.DeleteCompleted(channelName, DeleteCompletedEventType.EntitiyDeleted); + await _epiApi.DeleteCompletedAsync(channelName, DeleteCompletedEventType.EntitiyDeleted); return connectorEvent; } - public ConnectorEvent ChannelEntityUpdated(Entity channel, int entityId, string data) + public async Task ChannelEntityUpdatedAsync(Entity channel, int entityId, string data) { ConnectorEvent connectorEvent = ConnectorEventHelper.InitiateEvent(_config, ConnectorEventType.ChannelEntityUpdated, $"Received entity update for entity {entityId} in channel {channel.DisplayName}", 0); @@ -112,12 +113,12 @@ public ConnectorEvent ChannelEntityUpdated(Entity channel, int entityId, string return connectorEvent; string folderDateTime = DateTime.Now.ToString(Constants.PublicationFolderNameTimeComponent); - var resourceIncluded = false; + bool resourceIncluded = false; List structureEntities = _entityService.GetStructureEntitiesForEntityInChannel(_config.ChannelId, entityId); if (updatedEntity.EntityType.Id.Equals("Resource")) { - resourceIncluded = HandleResourceUpdate(updatedEntity, folderDateTime); + resourceIncluded = await HandleResourceUpdateAsync(updatedEntity, folderDateTime); } else { @@ -125,11 +126,11 @@ public ConnectorEvent ChannelEntityUpdated(Entity channel, int entityId, string if (updatedEntity.EntityType.Id.Equals("Item") && data != null && data.Split(',').Contains("SKUs")) { - HandleSkuUpdate(entityId, channel, connectorEvent, structureEntities, out resourceIncluded); + resourceIncluded = await HandleSkuUpdateAsync(entityId, channel, connectorEvent, structureEntities); } else if (updatedEntity.EntityType.Id.Equals("ChannelNode")) { - HandleChannelNodeUpdate(channel, structureEntities, connectorEvent); + await HandleChannelNodeUpdateAsync(channel, structureEntities, connectorEvent); return connectorEvent; } @@ -139,16 +140,16 @@ public ConnectorEvent ChannelEntityUpdated(Entity channel, int entityId, string IntegrationLogger.Write(LogLevel.Debug, "Starting automatic import!"); - _epiApi.ImportCatalog(catalogDocumentName); - _epiApi.NotifyEpiserverPostImport(catalogDocumentName); + await _epiApi.ImportCatalogAsync(catalogDocumentName); + await _epiApi.NotifyEpiserverPostImportAsync(catalogDocumentName); } string channelName = _mappingHelper.GetNameForEntity(channel, 100); - _epiApi.ImportUpdateCompleted(channelName, ImportUpdateCompletedEventType.EntityUpdated, resourceIncluded); + await _epiApi.ImportUpdateCompletedAsync(channelName, ImportUpdateCompletedEventType.EntityUpdated, resourceIncluded); return connectorEvent; } - public ConnectorEvent ChannelLinkAdded(Entity channel, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) + public async Task ChannelLinkAddedAsync(Entity channel, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) { ConnectorEvent connectorEvent = ConnectorEventHelper.InitiateEvent(_config, ConnectorEventType.ChannelLinkAdded, $"Received link added for sourceEntityId {sourceEntityId} and targetEntityId {targetEntityId} in channel {channel.DisplayName}", 0); @@ -165,10 +166,10 @@ public ConnectorEvent ChannelLinkAdded(Entity channel, int sourceEntityId, int t parentIds.Reverse(); parentIds.RemoveAt(0); - for (var i = 0; i < parentIds.Count - 1; i++) + for (int i = 0; i < parentIds.Count - 1; i++) { - int entityId = int.Parse(parentIds[i]); - int parentId = int.Parse(parentIds[i + 1]); + int entityId = Int32.Parse(parentIds[i]); + int parentId = Int32.Parse(parentIds[i + 1]); structureEntities.AddRange(RemoteManager.ChannelService.GetAllStructureEntitiesForEntityWithParentInChannel(channel.Id, entityId, parentId)); } @@ -180,8 +181,6 @@ public ConnectorEvent ChannelLinkAdded(Entity channel, int sourceEntityId, int t structureEntities.AddRange(RemoteManager.ChannelService.GetAllChannelStructureEntitiesFromPath(targetEntityPath)); } - - // Remove duplicates structureEntities = structureEntities.GroupBy(x => x.EntityId).Select(x => x.First()).ToList(); @@ -190,15 +189,15 @@ public ConnectorEvent ChannelLinkAdded(Entity channel, int sourceEntityId, int t ConnectorEventHelper.UpdateEvent(connectorEvent, "Done fetching channel entities", 10); - PublishEntities(channel, connectorEvent, structureEntities); + await PublishEntitiesAsync(channel, connectorEvent, structureEntities); string channelName = _mappingHelper.GetNameForEntity(channel, 100); - _epiApi.ImportUpdateCompleted(channelName, ImportUpdateCompletedEventType.LinkAdded, true); + await _epiApi.ImportUpdateCompletedAsync(channelName, ImportUpdateCompletedEventType.LinkAdded, true); return connectorEvent; } - public ConnectorEvent ChannelLinkDeleted(Entity channel, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) + public async Task ChannelLinkDeletedAsync(Entity channel, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) { ConnectorEvent connectorEvent = ConnectorEventHelper.InitiateEvent(_config, ConnectorEventType.ChannelLinkDeleted, $"Received link deleted for sourceEntityId {sourceEntityId} and targetEntityId {targetEntityId} in channel {channel.DisplayName.Data}", 0); @@ -208,20 +207,20 @@ public ConnectorEvent ChannelLinkDeleted(Entity channel, int sourceEntityId, int if (removalTarget.EntityType.Id == "Resource") { - DeleteResourceLink(removalTarget, removalSource); + await DeleteResourceLinkAsync(removalTarget, removalSource); } else { - DeleteLink(removalSource, removalTarget, linkTypeId); + await DeleteLinkAsync(removalSource, removalTarget, linkTypeId); } string channelName = _mappingHelper.GetNameForEntity(channel, 100); - _epiApi.DeleteCompleted(channelName, DeleteCompletedEventType.LinkDeleted); + await _epiApi.DeleteCompletedAsync(channelName, DeleteCompletedEventType.LinkDeleted); return connectorEvent; } - public ConnectorEvent ChannelLinkUpdated(Entity channel, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) + public async Task ChannelLinkUpdatedAsync(Entity channel, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) { List targetEntityStructure = _entityService.GetEntityInChannelWithParent(_config.ChannelId, targetEntityId, sourceEntityId); @@ -234,8 +233,8 @@ public ConnectorEvent ChannelLinkUpdated(Entity channel, int sourceEntityId, int $"Received link deleted for sourceEntityId {sourceEntityId} and targetEntityId {targetEntityId} in channel {channel.DisplayName.Data}", 0); Entity removalTarget = _entityService.GetEntity(targetEntityId, LoadLevel.DataAndLinks); Entity removalSource = _entityService.GetEntity(sourceEntityId, LoadLevel.DataAndLinks); - DeleteLink(removalSource, removalTarget, linkTypeId, true); - _epiApi.DeleteCompleted(channelName, DeleteCompletedEventType.LinkDeleted); + await DeleteLinkAsync(removalSource, removalTarget, linkTypeId, true); + await _epiApi.DeleteCompletedAsync(channelName, DeleteCompletedEventType.LinkDeleted); return deleteEvent; } @@ -254,15 +253,14 @@ public ConnectorEvent ChannelLinkUpdated(Entity channel, int sourceEntityId, int ConnectorEventHelper.UpdateEvent(connectorEvent, "Done fetching channel entities", 10); - PublishEntities(channel, connectorEvent, structureEntities); - + await PublishEntitiesAsync(channel, connectorEvent, structureEntities); - _epiApi.ImportUpdateCompleted(channelName, ImportUpdateCompletedEventType.LinkUpdated, true); + await _epiApi.ImportUpdateCompletedAsync(channelName, ImportUpdateCompletedEventType.LinkUpdated, true); return connectorEvent; } - public ConnectorEvent Publish(Entity channel) + public async Task PublishAsync(Entity channel) { ConnectorEvent publishEvent = ConnectorEventHelper.InitiateEvent(_config, ConnectorEventType.Publish, $"Publish started for channel: {channel.DisplayName.Data}", 0); ConnectorEventHelper.UpdateEvent(publishEvent, "Fetching all channel entities...", 1); @@ -271,7 +269,7 @@ public ConnectorEvent Publish(Entity channel) ConnectorEventHelper.UpdateEvent(publishEvent, "Fetched all channel entities. Generating catalog.xml...", 10); - CatalogElementContainer epiElements = _catalogDocumentFactory.GetEPiElements(channelStructureEntities); + CatalogElementContainer epiElements = await _catalogDocumentFactory.GetEPiElementsAsync(channelStructureEntities); XElement metaClasses = _catalogElementFactory.GetMetaClassesFromFieldSets(); XElement associationTypes = _catalogDocumentFactory.GetAssociationTypes(); @@ -281,51 +279,51 @@ public ConnectorEvent Publish(Entity channel) List resourceEntities = RemoteManager.ChannelService.GetAllChannelStructureEntitiesForTypeFromPath(channel.Id.ToString(), "Resource"); - PubilshToEpiserver(publishEvent, catalogDocument, resourceEntities, channel); + await PublishToEpiserverAsync(publishEvent, catalogDocument, resourceEntities, channel); return publishEvent; } - internal void PublishEntities(Entity channel, ConnectorEvent connectorEvent, List structureEntities) + internal async Task PublishEntitiesAsync(Entity channel, ConnectorEvent connectorEvent, List structureEntities) { ConnectorEventHelper.UpdateEvent(connectorEvent, "Generating catalog.xml...", 11); - CatalogElementContainer epiElements = _catalogDocumentFactory.GetEPiElements(structureEntities); + CatalogElementContainer epiElements = await _catalogDocumentFactory.GetEPiElementsAsync(structureEntities); XDocument catalogDocument = _catalogDocumentFactory.CreateImportDocument(channel, null, null, epiElements); LogCatalogProperties(epiElements); - PubilshToEpiserver(connectorEvent, catalogDocument, structureEntities, channel); + await PublishToEpiserverAsync(connectorEvent, catalogDocument, structureEntities, channel); } private static void LogCatalogProperties(CatalogElementContainer epiElements) { - IntegrationLogger.Write(LogLevel.Information, $"Catalog saved with the following: " + + IntegrationLogger.Write(LogLevel.Information, "Catalog saved with the following: " + $"Nodes: {epiElements.Nodes.Count}. " + $"Entries: {epiElements.Entries.Count}. " + $"Relations: {epiElements.Relations.Count}. " + $"Associations: {epiElements.Associations.Count}. "); } - private void Delete(Entity channelEntity, Entity deletedEntity) + private async Task DeleteAsync(Entity channelEntity, Entity deletedEntity) { switch (deletedEntity.EntityType.Id) { case "Resource": Guid resourceGuid = EpiserverEntryIdentifier.EntityIdToGuid(deletedEntity.Id); - _epiApi.DeleteResource(resourceGuid); + await _epiApi.DeleteResourceAsync(resourceGuid); break; case "Channel": - _epiApi.DeleteCatalog(deletedEntity.Id); + await _epiApi.DeleteCatalogAsync(deletedEntity.Id); break; case "ChannelNode": - _epiApi.DeleteCatalogNode(deletedEntity, channelEntity.Id); + await _epiApi.DeleteCatalogNodeAsync(deletedEntity, channelEntity.Id); break; case "Item": if ((_config.ItemsToSkus && _config.UseThreeLevelsInCommerce) || !_config.ItemsToSkus) { - _epiApi.DeleteCatalogEntry(deletedEntity); + await _epiApi.DeleteCatalogEntryAsync(deletedEntity); } if (_config.ItemsToSkus) @@ -343,17 +341,17 @@ private void Delete(Entity channelEntity, Entity deletedEntity) } } - _epiApi.DeleteSkus(entitiesToDelete); + await _epiApi.DeleteSkusAsync(entitiesToDelete); } break; default: - _epiApi.DeleteCatalogEntry(deletedEntity); + await _epiApi.DeleteCatalogEntryAsync(deletedEntity); break; } } - private void DeleteLink(Entity removalSource, Entity removalTarget, string linkTypeId, bool overrideIsRelation = false) + private async Task DeleteLinkAsync(Entity removalSource, Entity removalTarget, string linkTypeId, bool overrideIsRelation = false) { bool isRelation = _mappingHelper.IsRelation(linkTypeId) || overrideIsRelation; @@ -366,26 +364,25 @@ private void DeleteLink(Entity removalSource, Entity removalTarget, string linkT string sourceCode = _catalogCodeGenerator.GetEpiserverCode(removalSource); string targetCode = _catalogCodeGenerator.GetEpiserverCode(removalTarget); - _epiApi.DeleteLink(sourceCode, targetCode, isRelation); + await _epiApi.DeleteLinkAsync(sourceCode, targetCode, isRelation); } - private void DeleteResourceLink(Entity removedResource, Entity removalTarget) + private async Task DeleteResourceLinkAsync(Entity removedResource, Entity removalTarget) { Guid resourceGuid = EpiserverEntryIdentifier.EntityIdToGuid(removedResource.Id); string targetCode = _catalogCodeGenerator.GetEpiserverCode(removalTarget); - _epiApi.DeleteLink(resourceGuid, targetCode); + await _epiApi.DeleteLinkAsync(resourceGuid, targetCode); } - private void HandleChannelNodeUpdate(Entity channel, List structureEntities, ConnectorEvent entityUpdatedConnectorEvent) + private async Task HandleChannelNodeUpdateAsync(Entity channel, List structureEntities, ConnectorEvent entityUpdatedConnectorEvent) { - PublishEntities(channel, entityUpdatedConnectorEvent, structureEntities); - _epiApi.ImportUpdateCompleted(_pimFieldAdapter.GetDisplayName(channel, 100), ImportUpdateCompletedEventType.EntityUpdated, true); + await PublishEntitiesAsync(channel, entityUpdatedConnectorEvent, structureEntities); + await _epiApi.ImportUpdateCompletedAsync(_pimFieldAdapter.GetDisplayName(channel, 100), ImportUpdateCompletedEventType.EntityUpdated, true); } - private bool HandleResourceUpdate(Entity updatedEntity, string folderDateTime) + private async Task HandleResourceUpdateAsync(Entity updatedEntity, string folderDateTime) { - var resourceIncluded = false; XDocument resourceDocument = _resourceElementFactory.HandleResourceUpdate(updatedEntity, folderDateTime); string resourcesBasePath = Path.Combine(_config.ResourcesRootPath, folderDateTime); _documentFileHelper.SaveDocument(resourceDocument, resourcesBasePath); @@ -395,56 +392,55 @@ private bool HandleResourceUpdate(Entity updatedEntity, string folderDateTime) string baseFilePath = Path.Combine(_config.ResourcesRootPath, folderDateTime); string resourceXmlPath = Path.Combine(baseFilePath, "Resources.xml"); - _epiApi.ImportResources(resourceXmlPath, baseFilePath); + await _epiApi.ImportResourcesAsync(resourceXmlPath, baseFilePath); - _epiApi.NotifyEpiserverPostImport(resourceXmlPath); - resourceIncluded = true; + await _epiApi.NotifyEpiserverPostImportAsync(resourceXmlPath); - return resourceIncluded; + return true; } - private void HandleSkuUpdate(int entityId, + private async Task HandleSkuUpdateAsync(int entityId, Entity channelEntity, ConnectorEvent connectorEvent, - List structureEntities, - out bool resourceIncluded) + List structureEntities) { - resourceIncluded = false; + bool resourceIncluded = false; Field currentField = RemoteManager.DataService.GetField(entityId, "SKUs"); List fieldHistory = RemoteManager.DataService.GetFieldHistory(entityId, "SKUs"); Field previousField = fieldHistory.FirstOrDefault(f => f.Revision == currentField.Revision - 1); - string oldXml = string.Empty; - if (previousField != null && previousField.Data != null) + string oldXml = String.Empty; + if (previousField?.Data != null) { - oldXml = (string) previousField.Data; + oldXml = (string)previousField.Data; } - string newXml = string.Empty; + string newXml = String.Empty; if (currentField.Data != null) { - newXml = (string) currentField.Data; + newXml = (string)currentField.Data; } - List skusToDelete, skusToAdd; - PimFieldAdapter.CompareAndParseSkuXmls(oldXml, newXml, out skusToAdd, out skusToDelete); + PimFieldAdapter.CompareAndParseSkuXmls(oldXml, newXml, out List skusToAdd, out List skusToDelete); foreach (XElement skuToDelete in skusToDelete) { - string skuId = skuToDelete.Attribute("id").Value; - _epiApi.DeleteSku(skuId); + string skuId = skuToDelete.Attribute("id")?.Value; + await _epiApi.DeleteSkuAsync(skuId); } if (skusToAdd.Count > 0) { - PublishEntities(channelEntity, connectorEvent, structureEntities); + await PublishEntitiesAsync(channelEntity, connectorEvent, structureEntities); resourceIncluded = true; } + + return resourceIncluded; } - private void PubilshToEpiserver(ConnectorEvent connectorEvent, + private async Task PublishToEpiserverAsync(ConnectorEvent connectorEvent, XDocument catalogDocument, List structureEntitiesToGetResourcesFor, Entity channelEntity) @@ -461,22 +457,22 @@ private void PubilshToEpiserver(ConnectorEvent connectorEvent, ConnectorEventHelper.UpdateEvent(connectorEvent, "Done generating/saving Resource.xml, sending Catalog.xml to EPiServer...", 50); - _epiApi.ImportCatalog(savedCatalogDocument); + await _epiApi.ImportCatalogAsync(savedCatalogDocument); ConnectorEventHelper.UpdateEvent(connectorEvent, "Done sending Catalog.xml to EPiServer", 75); - _epiApi.NotifyEpiserverPostImport(savedCatalogDocument); + await _epiApi.NotifyEpiserverPostImportAsync(savedCatalogDocument); ConnectorEventHelper.UpdateEvent(connectorEvent, "Sending Resources to EPiServer...", 76); - _epiApi.ImportResources(resourceDocumentPath, resourcesBasePath); + await _epiApi.ImportResourcesAsync(resourceDocumentPath, resourcesBasePath); ConnectorEventHelper.UpdateEvent(connectorEvent, "Done sending Resources to EPiServer...", 99); - _epiApi.NotifyEpiserverPostImport(resourceDocumentPath); + await _epiApi.NotifyEpiserverPostImportAsync(resourceDocumentPath); string channelName = _mappingHelper.GetNameForEntity(channelEntity, 100); - _epiApi.ImportUpdateCompleted(channelName, ImportUpdateCompletedEventType.Publish, true); + await _epiApi.ImportUpdateCompletedAsync(channelName, ImportUpdateCompletedEventType.Publish, true); } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/Communication/EpiApi.cs b/src/EpiserverAdapter/Communication/EpiApi.cs index f2a4c51..a5d2715 100644 --- a/src/EpiserverAdapter/Communication/EpiApi.cs +++ b/src/EpiserverAdapter/Communication/EpiApi.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Epinova.InRiverConnector.EpiserverAdapter.Helpers; using Epinova.InRiverConnector.Interfaces; using Epinova.InRiverConnector.Interfaces.Enums; using inRiver.Integration.Logging; @@ -23,16 +22,14 @@ static EpiApi() Semaphore = new SemaphoreSlim(1, 1); } - public EpiApi(IConfiguration config, - CatalogCodeGenerator catalogCodeGenerator, - PimFieldAdapter pimFieldAdapter) + public EpiApi(IConfiguration config, CatalogCodeGenerator catalogCodeGenerator) { _config = config; _catalogCodeGenerator = catalogCodeGenerator; _httpClient = new HttpClientInvoker(config); } - public async Task DeleteLink(string sourceCode, string targetCode, bool isRelation) + public async Task DeleteLinkAsync(string sourceCode, string targetCode, bool isRelation) { await ExecuteWithinLockAsync( () => @@ -45,7 +42,7 @@ await ExecuteWithinLockAsync( ); } - public async Task DeleteLink(Guid resourceGuid, string targetCode) + public async Task DeleteLinkAsync(Guid resourceGuid, string targetCode) { await ExecuteWithinLockAsync( () => @@ -57,7 +54,7 @@ await ExecuteWithinLockAsync( ); } - public async Task DeleteResource(Guid resourceGuid) + public async Task DeleteResourceAsync(Guid resourceGuid) { await ExecuteWithinLockAsync( () => @@ -66,7 +63,7 @@ await ExecuteWithinLockAsync( ); } - internal async Task DeleteCatalog(int catalogId) + internal async Task DeleteCatalogAsync(int catalogId) { await ExecuteWithinLockAsync( () => @@ -74,7 +71,7 @@ await ExecuteWithinLockAsync( ); } - internal async Task DeleteCatalogEntry(Entity entity) + internal async Task DeleteCatalogEntryAsync(Entity entity) { string code = _catalogCodeGenerator.GetEpiserverCode(entity); await ExecuteWithinLockAsync( @@ -83,7 +80,7 @@ await ExecuteWithinLockAsync( ); } - internal async Task DeleteCatalogNode(Entity catalogNode, int catalogId) + internal async Task DeleteCatalogNodeAsync(Entity catalogNode, int catalogId) { await ExecuteWithinLockAsync( () => @@ -92,7 +89,7 @@ await ExecuteWithinLockAsync( ); } - internal async Task DeleteCompleted(string catalogName, DeleteCompletedEventType eventType) + internal async Task DeleteCompletedAsync(string catalogName, DeleteCompletedEventType eventType) { await ExecuteWithinLockAsync( () => @@ -104,7 +101,7 @@ await ExecuteWithinLockAsync( ); } - internal async Task DeleteSku(string skuId) + internal async Task DeleteSkuAsync(string skuId) { await ExecuteWithinLockAsync( () => @@ -112,7 +109,7 @@ await ExecuteWithinLockAsync( ); } - internal async Task DeleteSkus(List skuIds) + internal async Task DeleteSkusAsync(List skuIds) { await ExecuteWithinLockAsync( () => @@ -120,7 +117,7 @@ await ExecuteWithinLockAsync( ); } - internal async Task ImportCatalog(string filePath) + internal async Task ImportCatalogAsync(string filePath) { await ExecuteWithinLockAsync( () => @@ -129,7 +126,7 @@ await ExecuteWithinLockAsync( ); } - internal async Task ImportResources(string resourceDocumentFilePath, string baseFilePath) + internal async Task ImportResourcesAsync(string resourceDocumentFilePath, string baseFilePath) { var importer = new ResourceImporter(_config, _httpClient); await ExecuteWithinLockAsync( @@ -138,8 +135,7 @@ await ExecuteWithinLockAsync( ); } - internal async Task ImportUpdateCompleted(string catalogName, ImportUpdateCompletedEventType eventType, - bool resourceIncluded) + internal async Task ImportUpdateCompletedAsync(string catalogName, ImportUpdateCompletedEventType eventType, bool resourceIncluded) { var data = new ImportUpdateCompletedData { @@ -153,7 +149,7 @@ await ExecuteWithinLockAsync( ); } - internal async Task MoveNodeToRootIfNeeded(int entityId) + internal async Task MoveNodeToRootIfNeededAsync(int entityId) { string entryNodeId = _catalogCodeGenerator.GetEpiserverCode(entityId); await ExecuteWithinLockAsync( @@ -162,9 +158,9 @@ await ExecuteWithinLockAsync( ); } - internal async Task NotifyEpiserverPostImport(string filepath) + internal async Task NotifyEpiserverPostImportAsync(string filepath) { - if (string.IsNullOrEmpty(_config.HttpPostUrl)) + if (String.IsNullOrEmpty(_config.HttpPostUrl)) return; await ExecuteWithinLockAsync( @@ -194,4 +190,4 @@ private async Task ExecuteWithinLockAsync(Func action, } } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/ConfigDefaults.cs b/src/EpiserverAdapter/ConfigDefaults.cs index 0b0f699..11c936f 100644 --- a/src/EpiserverAdapter/ConfigDefaults.cs +++ b/src/EpiserverAdapter/ConfigDefaults.cs @@ -2,17 +2,17 @@ { public class ConfigDefaults { + public static string CvlData = "Keys|Values|KeysAndValues"; + public static string EpiApiKey = "SomeGreatKey123"; + public static string EpiEndpoint = "https://www.example.com/inriverapi/InriverDataImport/"; + public static string EpiTimeout = "1"; public static string ExportEntities = "Product,Item,ChannelNode"; public static string ForceIncludeLinkedContent = "False"; + public static string ItemToSkus = "false"; + public static string LanguageMapping = "enen-us"; public static string PublishFolder = @"C:\temp\Publish\Epi"; - public static string ResourcesPublishFolder = @"C:\temp\Publish\Epi\Resources"; public static string ResourceConfiguration = "Preview"; - public static string LanguageMapping = "enen-us"; - public static string ItemToSkus = "false"; - public static string CvlData = "Keys|Values|KeysAndValues"; + public static string ResourcesPublishFolder = @"C:\temp\Publish\Epi\Resources"; public static string UseThreeLevelsinCommerce = "false"; - public static string EpiEndpoint = "https://www.example.com/inriverapi/InriverDataImport/"; - public static string EpiApiKey = "SomeGreatKey123"; - public static string EpiTimeout = "1"; } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/ConfigKeys.cs b/src/EpiserverAdapter/ConfigKeys.cs index c3f1199..9b17c84 100644 --- a/src/EpiserverAdapter/ConfigKeys.cs +++ b/src/EpiserverAdapter/ConfigKeys.cs @@ -2,26 +2,26 @@ { public class ConfigKeys { - public static string EpiTimeout = "EPI_RESTTIMEOUT"; + public static string BatchSize = "BATCH_SIZE"; + public static string BundleTypes = "BUNDLE_ENTITYTYPES"; + public static string ChannelId = "CHANNEL_ID"; + public static string CvlData = "CVL_DATA"; + public static string DynamicPackageTypes = "DYNAMIC_PACKAGE_ENTITYTYPES"; public static string EpiApiKey = "EPI_APIKEY"; + public static string EpiCodeFields = "EPI_CODE_FIELDS"; public static string EpiEndpoint = "EPI_ENDPOINT_URL"; + public static string EpiNameFields = "EPI_NAME_FIELDS"; + public static string EpiTimeout = "EPI_RESTTIMEOUT"; + public static string ExcludeFields = "EXCLUDE_FIELDS"; public static string ExportEntities = "EXPORT_ENTITIES"; - public static string ChannelId = "CHANNEL_ID"; - public static string PublishFolder = "PUBLISH_FOLDER"; + public static string ForceIncludeLinkedContent = "FORCE_INCLUDE_LINKED_CONTENT"; public static string HttpPostUrl = "HTTP_POST_URL"; + public static string ItemToSkus = "ITEM_TO_SKUs"; public static string LanguageMapping = "LANGUAGE_MAPPING"; - public static string EpiNameFields = "EPI_NAME_FIELDS"; + public static string PackageTypes = "PACKAGE_ENTITYTYPES"; + public static string PublishFolder = "PUBLISH_FOLDER"; + public static string ResourceConfiguration = "RESOURCE_CONFIGURATION"; public static string ResourcesPublishFolder = "PUBLISH_FOLDER_RESOURCES"; public static string UseThreeLevelsInCommerce = "USE_THREE_LEVELS_IN_COMMERCE"; - public static string EpiCodeFields = "EPI_CODE_FIELDS"; - public static string ResourceConfiguration = "RESOURCE_CONFIGURATION"; - public static string ItemToSkus = "ITEM_TO_SKUs"; - public static string BatchSize = "BATCH_SIZE"; - public static string BundleTypes = "BUNDLE_ENTITYTYPES"; - public static string PackageTypes = "PACKAGE_ENTITYTYPES"; - public static string DynamicPackageTypes = "DYNAMIC_PACKAGE_ENTITYTYPES"; - public static string ExcludeFields = "EXCLUDE_FIELDS"; - public static string CvlData = "CVL_DATA"; - public static string ForceIncludeLinkedContent = "FORCE_INCLUDE_LINKED_CONTENT"; } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/Configuration.cs b/src/EpiserverAdapter/Configuration.cs index 57d534c..1e84d88 100644 --- a/src/EpiserverAdapter/Configuration.cs +++ b/src/EpiserverAdapter/Configuration.cs @@ -13,28 +13,28 @@ namespace Epinova.InRiverConnector.EpiserverAdapter { public class Configuration : IConfiguration { - private readonly Dictionary _settings; - private readonly List _epiFieldsIninRiver; - private bool? _useThreeLevelsInCommerce; - private CultureInfo _channelDefaultLanguage; + private readonly Dictionary _settings; + private int _batchsize; private string _channelDefaultCurrency; + private CultureInfo _channelDefaultLanguage; private string _channelWeightBase; private Dictionary _epiCodeMapping; - private Dictionary _resourceConfiugExtensions; - private Dictionary _languageMapping; private Dictionary _epiNameMapping; + private HashSet _excludedFields; + private List _exportEnabledEntityTypes; private List _exportEnabledLinkTypes; private bool _itemsToSkus; - private HashSet _excludedFields; - private int _batchsize; + private Dictionary _languageMapping; + private Dictionary _resourceConfiugExtensions; + private bool? _useThreeLevelsInCommerce; public Configuration(string id) { _settings = RemoteManager.UtilityService.GetConnector(id).Settings; var settingsValidator = new SettingsValidator(_settings); settingsValidator.ValidateSettings(); - + Id = id; Endpoints = new EndpointCollection(EpiEndpoint); LinkTypes = new List(RemoteManager.ModelService.GetAllLinkTypes()); @@ -42,118 +42,216 @@ public Configuration(string id) _epiFieldsIninRiver = new List { "startdate", "enddate", "displaytemplate", "seodescription", "seokeywords", "seotitle", "seouri", "skus" }; } - public int EpiRestTimeout => int.Parse(_settings[ConfigKeys.EpiTimeout]); - public string EpiApiKey => _settings[ConfigKeys.EpiApiKey]; - public string EpiEndpoint => _settings[ConfigKeys.EpiEndpoint]; - public bool ForceIncludeLinkedContent => bool.Parse(_settings[ConfigKeys.ForceIncludeLinkedContent]); - - public EndpointCollection Endpoints { get; set; } + public static string CVLKeyDelimiter => "||"; public static string OriginalDisplayConfiguration => "Original"; - public static string CVLKeyDelimiter => "||"; - public string Id { get; } + public CVLDataMode ActiveCVLDataMode => !_settings.ContainsKey(ConfigKeys.CvlData) ? CVLDataMode.Undefined : StringToCVLDataMode(_settings[ConfigKeys.CvlData]); - public List LinkTypes { get; set; } + public LinkType[] AssociationLinkTypes + { + get + { + if (_exportEnabledLinkTypes != null) + return _exportEnabledLinkTypes.ToArray(); - public int ChannelId + _exportEnabledLinkTypes = new List(); + List allLinkTypes = RemoteManager.ModelService.GetAllLinkTypes(); + + LinkType productItemLink = allLinkTypes.Where(x => x.SourceEntityTypeId.Equals("Product") && x.TargetEntityTypeId.Equals("Item")) + .OrderBy(l => l.Index) + .FirstOrDefault(); + + foreach (LinkType linkType in allLinkTypes) + { + if (linkType.TargetEntityTypeId == "Specification") + continue; + + if (linkType.IsProductItemLink() && linkType.Id == productItemLink?.Id) + continue; + + if (linkType.SourceEntityTypeIsChannelNode()) + continue; + + if (BundleEntityTypes.Contains(linkType.SourceEntityTypeId) || + PackageEntityTypes.Contains(linkType.SourceEntityTypeId)) + continue; + + if (ExportEnabledEntityTypes.Any(x => x.Id == linkType.SourceEntityTypeId) && + ExportEnabledEntityTypes.Any(x => x.Id == linkType.TargetEntityTypeId)) + { + _exportEnabledLinkTypes.Add(linkType); + } + } + + IntegrationLogger.Write(LogLevel.Debug, $"ExportEnabledLinkTypes: {string.Join(",", _exportEnabledLinkTypes)}."); + + return _exportEnabledLinkTypes.ToArray(); + } + } + + public int BatchSize { get { - if (!_settings.ContainsKey(ConfigKeys.ChannelId)) + if (!_settings.ContainsKey(ConfigKeys.BatchSize)) + return Int32.MaxValue; + + string value = _settings[ConfigKeys.BatchSize]; + + if (!Int32.TryParse(value, out _batchsize) || value == "0") { - return 0; + _batchsize = Int32.MaxValue; } - return int.Parse(_settings[ConfigKeys.ChannelId]); + return _batchsize; } } - - public string PublicationsRootPath => !_settings.ContainsKey(ConfigKeys.PublishFolder) ? - @"C:\temp\Publish\Epi" : - _settings[ConfigKeys.PublishFolder]; - private List _exportEnabledEntityTypes; - public List ExportEnabledEntityTypes + public string[] BundleEntityTypes => SplitString(ConfigKeys.BundleTypes); + + public string ChannelDefaultCurrency { get { - if (_exportEnabledEntityTypes != null) - return _exportEnabledEntityTypes; + if (String.IsNullOrEmpty(_channelDefaultCurrency)) + { + _channelDefaultCurrency = "USD"; + } - if (!_settings.ContainsKey(ConfigKeys.ExportEntities)) - throw new Exception($"Need to add exportable entities (config value {ConfigKeys.ExportEntities}. Default value is: {ConfigDefaults.ExportEntities}."); + return _channelDefaultCurrency; + } - var list = _settings[ConfigKeys.ExportEntities].Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries).ToList(); - var allEntityTypes = RemoteManager.ModelService.GetAllEntityTypes(); - _exportEnabledEntityTypes = allEntityTypes.Where(x => list.Contains(x.Id)).ToList(); - IntegrationLogger.Write(LogLevel.Debug, $"ExportEnabledEntityTypes: {string.Join(",", _exportEnabledEntityTypes)}."); + set => _channelDefaultCurrency = value; + } - return _exportEnabledEntityTypes; + public CultureInfo ChannelDefaultLanguage + { + get => _channelDefaultLanguage ?? (_channelDefaultLanguage = new CultureInfo("en-us")); + set => _channelDefaultLanguage = value; + } + + + public string ChannelDefaultWeightBase + { + get + { + if (String.IsNullOrEmpty(_channelWeightBase)) + { + _channelWeightBase = "kg"; + } + + return _channelWeightBase; } + set => _channelWeightBase = value; } - public string HttpPostUrl + public int ChannelId { get { - if (!_settings.ContainsKey(ConfigKeys.HttpPostUrl)) + if (!_settings.ContainsKey(ConfigKeys.ChannelId)) { - return null; + return 0; } - return _settings[ConfigKeys.HttpPostUrl]; + return Int32.Parse(_settings[ConfigKeys.ChannelId]); } } - public Dictionary LanguageMapping + public string ChannelIdPrefix { get; set; } = String.Empty; + public string[] DynamicPackageEntityTypes => SplitString(ConfigKeys.DynamicPackageTypes); + public EndpointCollection Endpoints { get; set; } + public string EpiApiKey => _settings[ConfigKeys.EpiApiKey]; + + public Dictionary EpiCodeMapping { get { - if (_languageMapping != null) - return _languageMapping; + if (_epiCodeMapping != null) + return _epiCodeMapping; - if (!_settings.ContainsKey(ConfigKeys.LanguageMapping)) + _epiCodeMapping = new Dictionary(); + + if (!_settings.ContainsKey(ConfigKeys.EpiCodeFields)) { - return new Dictionary(); + return _epiCodeMapping; } - string mappingXml = _settings[ConfigKeys.LanguageMapping]; + string rawValue = _settings[ConfigKeys.EpiCodeFields]; - _languageMapping = new Dictionary(); + if (String.IsNullOrEmpty(rawValue)) + return _epiCodeMapping; - XmlDocument doc = new XmlDocument(); - doc.LoadXml(mappingXml); + List fieldTypes = RemoteManager.ModelService.GetAllFieldTypes(); - List allLanguages = RemoteManager.UtilityService.GetAllLanguages(); + string[] values = rawValue.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - if (doc.DocumentElement == null) - return _languageMapping; + foreach (string val in values) + { + FieldType fieldType = fieldTypes.FirstOrDefault(x => x.Id.Equals(val, StringComparison.InvariantCultureIgnoreCase)); + if (fieldType != null && !_epiCodeMapping.ContainsKey(fieldType.EntityTypeId)) + { + _epiCodeMapping.Add(fieldType.EntityTypeId, fieldType.Id); + } + } - foreach (XmlNode languageNode in doc.DocumentElement) + return _epiCodeMapping; + } + } + + public string EpiEndpoint => _settings[ConfigKeys.EpiEndpoint]; + + public HashSet EPiFieldsIninRiver + { + get + { + if (_excludedFields != null) { - XmlElement epiLanguage = languageNode["epi"]; - XmlElement inriverLanguage = languageNode["inriver"]; + return _excludedFields; + } - if (epiLanguage != null && inriverLanguage != null) + if (!_settings.ContainsKey(ConfigKeys.ExcludeFields) || String.IsNullOrEmpty(_settings[ConfigKeys.ExcludeFields])) + { + var excludedFieldTypes = new HashSet(); + foreach (string baseField in _epiFieldsIninRiver) { - var episerverCulture = new CultureInfo(epiLanguage.InnerText); - var pimCulture = new CultureInfo(inriverLanguage.InnerText); - - if (!allLanguages.Exists(ci => ci.LCID == pimCulture.LCID)) + foreach (EntityType entityType in ExportEnabledEntityTypes) { - throw new Exception($"ERROR: Mapping Language incorrect, {inriverLanguage.InnerText} is not a valid pim culture info"); + excludedFieldTypes.Add(entityType.Id.ToLower() + baseField); } + } - _languageMapping.Add(episerverCulture, pimCulture); + excludedFieldTypes.Add("skus"); + + _excludedFields = excludedFieldTypes; + return _excludedFields; + } + else + { + var excludedFieldTypes = new HashSet(); + foreach (string baseField in _epiFieldsIninRiver) + { + foreach (EntityType entityType in ExportEnabledEntityTypes) + { + excludedFieldTypes.Add(entityType.Id.ToLower() + baseField); + } } - else + + excludedFieldTypes.Add("skus"); + + string[] fields = _settings[ConfigKeys.ExcludeFields].Split(','); + foreach (string field in fields) { - throw new Exception("ERROR: Mapping language is missing."); + if (!excludedFieldTypes.Contains(field.ToLower())) + { + excludedFieldTypes.Add(field.ToLower()); + } } - } - return _languageMapping; + _excludedFields = excludedFieldTypes; + return _excludedFields; + } } } @@ -168,22 +266,22 @@ public Dictionary EpiNameMapping if (!_settings.ContainsKey(ConfigKeys.EpiNameFields)) return _epiNameMapping; - - var value = _settings[ConfigKeys.EpiNameFields]; - if (string.IsNullOrEmpty(value)) + string value = _settings[ConfigKeys.EpiNameFields]; + + if (String.IsNullOrEmpty(value)) return _epiNameMapping; List fieldTypes = RemoteManager.ModelService.GetAllFieldTypes(); - var values = value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + string[] values = value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - foreach (var val in values) + foreach (string val in values) { - if (string.IsNullOrEmpty(val)) + if (String.IsNullOrEmpty(val)) continue; - var fieldType = fieldTypes.FirstOrDefault(fT => fT.Id.Equals(val, StringComparison.InvariantCultureIgnoreCase)); + FieldType fieldType = fieldTypes.FirstOrDefault(fT => fT.Id.Equals(val, StringComparison.InvariantCultureIgnoreCase)); if (fieldType != null && !_epiNameMapping.ContainsKey(fieldType.EntityTypeId)) { @@ -195,114 +293,112 @@ public Dictionary EpiNameMapping } } - public string ResourcesRootPath + public int EpiRestTimeout => Int32.Parse(_settings[ConfigKeys.EpiTimeout]); + + public List ExportEnabledEntityTypes { get { - if (!_settings.ContainsKey(ConfigKeys.ResourcesPublishFolder)) - { - return @"C:\temp\Publish\Epi\Resources"; - } + if (_exportEnabledEntityTypes != null) + return _exportEnabledEntityTypes; - return _settings[ConfigKeys.ResourcesPublishFolder]; + if (!_settings.ContainsKey(ConfigKeys.ExportEntities)) + throw new Exception($"Need to add exportable entities (config value {ConfigKeys.ExportEntities}. Default value is: {ConfigDefaults.ExportEntities}."); + + List list = _settings[ConfigKeys.ExportEntities].Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList(); + List allEntityTypes = RemoteManager.ModelService.GetAllEntityTypes(); + _exportEnabledEntityTypes = allEntityTypes.Where(x => list.Contains(x.Id)).ToList(); + IntegrationLogger.Write(LogLevel.Debug, $"ExportEnabledEntityTypes: {string.Join(",", _exportEnabledEntityTypes)}."); + + return _exportEnabledEntityTypes; } } - public bool UseThreeLevelsInCommerce + public bool ForceIncludeLinkedContent => bool.Parse(_settings[ConfigKeys.ForceIncludeLinkedContent]); + + public string HttpPostUrl { get { - if (_useThreeLevelsInCommerce != null) - return (bool) _useThreeLevelsInCommerce; - - if (!_settings.ContainsKey(ConfigKeys.UseThreeLevelsInCommerce)) + if (!_settings.ContainsKey(ConfigKeys.HttpPostUrl)) { - _useThreeLevelsInCommerce = false; - return _useThreeLevelsInCommerce.Value; + return null; } - var value = _settings[ConfigKeys.UseThreeLevelsInCommerce]; - - _useThreeLevelsInCommerce = !string.IsNullOrEmpty(value) && bool.Parse(value); - - return (bool)_useThreeLevelsInCommerce; + return _settings[ConfigKeys.HttpPostUrl]; } } - public CultureInfo ChannelDefaultLanguage - { - get => _channelDefaultLanguage ?? (_channelDefaultLanguage = new CultureInfo("en-us")); - set => _channelDefaultLanguage = value; - } + public string Id { get; } - public string ChannelDefaultCurrency + public bool ItemsToSkus { get { - if (string.IsNullOrEmpty(_channelDefaultCurrency)) + string value = _settings[ConfigKeys.ItemToSkus]; + if (!Boolean.TryParse(value, out _itemsToSkus)) { - _channelDefaultCurrency = "USD"; + _itemsToSkus = false; } - - return _channelDefaultCurrency; - } - set => _channelDefaultCurrency = value; + return _itemsToSkus; + } } - public Dictionary EpiCodeMapping + public Dictionary LanguageMapping { get { - if (_epiCodeMapping != null) - return _epiCodeMapping; - - _epiCodeMapping = new Dictionary(); + if (_languageMapping != null) + return _languageMapping; - if (!_settings.ContainsKey(ConfigKeys.EpiCodeFields)) + if (!_settings.ContainsKey(ConfigKeys.LanguageMapping)) { - return _epiCodeMapping; + return new Dictionary(); } - var rawValue = _settings[ConfigKeys.EpiCodeFields]; + string mappingXml = _settings[ConfigKeys.LanguageMapping]; - if (string.IsNullOrEmpty(rawValue)) - return _epiCodeMapping; + _languageMapping = new Dictionary(); - var fieldTypes = RemoteManager.ModelService.GetAllFieldTypes(); + var doc = new XmlDocument(); + doc.LoadXml(mappingXml); + + List allLanguages = RemoteManager.UtilityService.GetAllLanguages(); - var values = rawValue.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + if (doc.DocumentElement == null) + return _languageMapping; - foreach (var val in values) + foreach (XmlNode languageNode in doc.DocumentElement) { - var fieldType = fieldTypes.FirstOrDefault(x => x.Id.Equals(val, StringComparison.InvariantCultureIgnoreCase)); - if (fieldType != null && !_epiCodeMapping.ContainsKey(fieldType.EntityTypeId)) - { - _epiCodeMapping.Add(fieldType.EntityTypeId, fieldType.Id); - } - } + XmlElement epiLanguage = languageNode["epi"]; + XmlElement inriverLanguage = languageNode["inriver"]; - return _epiCodeMapping; - } - } + if (epiLanguage != null && inriverLanguage != null) + { + var episerverCulture = new CultureInfo(epiLanguage.InnerText); + var pimCulture = new CultureInfo(inriverLanguage.InnerText); - + if (!allLanguages.Exists(ci => ci.LCID == pimCulture.LCID)) + { + throw new Exception($"ERROR: Mapping Language incorrect, {inriverLanguage.InnerText} is not a valid pim culture info"); + } - public string ChannelDefaultWeightBase - { - get - { - if (string.IsNullOrEmpty(_channelWeightBase)) - { - _channelWeightBase = "kg"; + _languageMapping.Add(episerverCulture, pimCulture); + } + else + { + throw new Exception("ERROR: Mapping language is missing."); + } } - return _channelWeightBase; + return _languageMapping; } - set => _channelWeightBase = value; } - public string ChannelIdPrefix { get; set; } = string.Empty; + public List LinkTypes { get; set; } + public string[] PackageEntityTypes => SplitString(ConfigKeys.PackageTypes); + public string PublicationsRootPath => !_settings.ContainsKey(ConfigKeys.PublishFolder) ? @"C:\temp\Publish\Epi" : _settings[ConfigKeys.PublishFolder]; public string[] ResourceConfigurations { @@ -313,166 +409,80 @@ public string[] ResourceConfigurations return new string[0]; } - var resourceConfWithExt = ParseResourceConfig(_settings[ConfigKeys.ResourceConfiguration]); + Dictionary resourceConfWithExt = ParseResourceConfig(_settings[ConfigKeys.ResourceConfiguration]); return resourceConfWithExt.Keys.ToArray(); } } - public Dictionary ResourceConfiugurationExtensions => _resourceConfiugExtensions ?? - (_resourceConfiugExtensions = ParseResourceConfig(_settings[ConfigKeys.ResourceConfiguration])); + public Dictionary ResourceConfiugurationExtensions => _resourceConfiugExtensions ?? + (_resourceConfiugExtensions = ParseResourceConfig(_settings[ConfigKeys.ResourceConfiguration])); - public LinkType[] AssociationLinkTypes + public string ResourcesRootPath { get { - if (_exportEnabledLinkTypes != null) - return _exportEnabledLinkTypes.ToArray(); - - _exportEnabledLinkTypes = new List(); - List allLinkTypes = RemoteManager.ModelService.GetAllLinkTypes(); - - var productItemLink = allLinkTypes.Where(x => x.SourceEntityTypeId.Equals("Product") && x.TargetEntityTypeId.Equals("Item")) - .OrderBy(l => l.Index) - .FirstOrDefault(); - - foreach (var linkType in allLinkTypes) + if (!_settings.ContainsKey(ConfigKeys.ResourcesPublishFolder)) { - if (linkType.TargetEntityTypeId == "Specification") - continue; - - if (linkType.IsProductItemLink() && linkType.Id == productItemLink?.Id) - continue; - - if (linkType.SourceEntityTypeIsChannelNode()) - continue; - - if (BundleEntityTypes.Contains(linkType.SourceEntityTypeId) || - PackageEntityTypes.Contains(linkType.SourceEntityTypeId)) - continue; - - if (ExportEnabledEntityTypes.Any(x => x.Id == linkType.SourceEntityTypeId) && - ExportEnabledEntityTypes.Any(x => x.Id == linkType.TargetEntityTypeId)) - { - _exportEnabledLinkTypes.Add(linkType); - } + return @"C:\temp\Publish\Epi\Resources"; } - IntegrationLogger.Write(LogLevel.Debug, $"ExportEnabledLinkTypes: {string.Join(",", _exportEnabledLinkTypes)}."); - - return _exportEnabledLinkTypes.ToArray(); + return _settings[ConfigKeys.ResourcesPublishFolder]; } } - public bool ItemsToSkus + public bool UseThreeLevelsInCommerce { get { - var value = _settings[ConfigKeys.ItemToSkus]; - if (!bool.TryParse(value, out _itemsToSkus)) + if (_useThreeLevelsInCommerce != null) + return (bool)_useThreeLevelsInCommerce; + + if (!_settings.ContainsKey(ConfigKeys.UseThreeLevelsInCommerce)) { - _itemsToSkus = false; + _useThreeLevelsInCommerce = false; + return _useThreeLevelsInCommerce.Value; } - return _itemsToSkus; + string value = _settings[ConfigKeys.UseThreeLevelsInCommerce]; + + _useThreeLevelsInCommerce = !String.IsNullOrEmpty(value) && bool.Parse(value); + + return (bool)_useThreeLevelsInCommerce; } } - public int BatchSize + private static Dictionary ParseResourceConfig(string setting) { - get + var settingsDictionary = new Dictionary(); + if (String.IsNullOrEmpty(setting)) { - if (!_settings.ContainsKey(ConfigKeys.BatchSize)) - return int.MaxValue; - - var value = _settings[ConfigKeys.BatchSize]; - - if (!int.TryParse(value, out _batchsize) || value == "0") - { - _batchsize = int.MaxValue; - } - - return _batchsize; + return settingsDictionary; } - } - public string[] BundleEntityTypes => SplitString(ConfigKeys.BundleTypes); - public string[] PackageEntityTypes => SplitString(ConfigKeys.PackageTypes); - public string[] DynamicPackageEntityTypes => SplitString(ConfigKeys.DynamicPackageTypes); + setting = setting.Replace(" ", String.Empty); - public HashSet EPiFieldsIninRiver - { - get - { - if (_excludedFields != null) - { - return _excludedFields; - } + string[] resouceConfs = setting.Split(','); - if (!_settings.ContainsKey(ConfigKeys.ExcludeFields) || string.IsNullOrEmpty(_settings[ConfigKeys.ExcludeFields])) + foreach (string resouceConf in resouceConfs) + { + if (resouceConf.Contains(':')) { - HashSet excludedFieldTypes = new HashSet(); - foreach (string baseField in _epiFieldsIninRiver) - { - foreach (var entityType in ExportEnabledEntityTypes) - { - excludedFieldTypes.Add(entityType.Id.ToLower() + baseField); - } - } - - excludedFieldTypes.Add("skus"); + string[] parts = resouceConf.Split(':'); - _excludedFields = excludedFieldTypes; - return _excludedFields; + settingsDictionary.Add(parts[0], parts[1]); } else { - HashSet excludedFieldTypes = new HashSet(); - foreach (string baseField in _epiFieldsIninRiver) - { - foreach (var entityType in ExportEnabledEntityTypes) - { - excludedFieldTypes.Add(entityType.Id.ToLower() + baseField); - } - } - - excludedFieldTypes.Add("skus"); - - var fields = _settings[ConfigKeys.ExcludeFields].Split(','); - foreach (string field in fields) - { - if (!excludedFieldTypes.Contains(field.ToLower())) - { - excludedFieldTypes.Add(field.ToLower()); - } - } - - _excludedFields = excludedFieldTypes; - return _excludedFields; + settingsDictionary.Add(resouceConf, String.Empty); } } - } - - public CVLDataMode ActiveCVLDataMode => !_settings.ContainsKey(ConfigKeys.CvlData) ? CVLDataMode.Undefined : StringToCVLDataMode(_settings[ConfigKeys.CvlData]); - private string[] SplitString(string settingKey) - { - if(!_settings.ContainsKey(settingKey)) - return new string[0]; - - var setting = _settings[settingKey]; - - if (string.IsNullOrEmpty(setting)) - return new string[0]; - - setting = setting.Replace(" ", string.Empty); - return setting.Split(','); + return settingsDictionary; } private static CVLDataMode StringToCVLDataMode(string str) { - CVLDataMode mode; - - if (!Enum.TryParse(str, out mode)) + if (!Enum.TryParse(str, out CVLDataMode mode)) { IntegrationLogger.Write(LogLevel.Error, $"Could not parse CVLDataMode for string {str}"); } @@ -480,33 +490,18 @@ private static CVLDataMode StringToCVLDataMode(string str) return mode; } - private Dictionary ParseResourceConfig(string setting) + private string[] SplitString(string settingKey) { - Dictionary settingsDictionary = new Dictionary(); - if (string.IsNullOrEmpty(setting)) - { - return settingsDictionary; - } - - setting = setting.Replace(" ", string.Empty); + if (!_settings.ContainsKey(settingKey)) + return new string[0]; - var resouceConfs = setting.Split(','); - - foreach (var resouceConf in resouceConfs) - { - if (resouceConf.Contains(':')) - { - var parts = resouceConf.Split(':'); + string setting = _settings[settingKey]; - settingsDictionary.Add(parts[0], parts[1]); - } - else - { - settingsDictionary.Add(resouceConf, string.Empty); - } - } + if (String.IsNullOrEmpty(setting)) + return new string[0]; - return settingsDictionary; + setting = setting.Replace(" ", String.Empty); + return setting.Split(','); } } } diff --git a/src/EpiserverAdapter/Constants.cs b/src/EpiserverAdapter/Constants.cs index d7159cc..37af4bd 100644 --- a/src/EpiserverAdapter/Constants.cs +++ b/src/EpiserverAdapter/Constants.cs @@ -3,8 +3,7 @@ public static class Constants { public static string CatalogExportFilename = "Catalog.xml"; - public static string ResourceExportFilename = "Resources.xml"; - public static string PublicationFolderNameTimeComponent = "yyyyMMdd-HHmmss.fff"; + public static string ResourceExportFilename = "Resources.xml"; } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/CvlUpdater.cs b/src/EpiserverAdapter/CvlUpdater.cs index c1665cd..ee905c0 100644 --- a/src/EpiserverAdapter/CvlUpdater.cs +++ b/src/EpiserverAdapter/CvlUpdater.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; +using System.Xml.Linq; using Epinova.InRiverConnector.EpiserverAdapter.Communication; using Epinova.InRiverConnector.EpiserverAdapter.Helpers; using Epinova.InRiverConnector.EpiserverAdapter.XmlFactories; @@ -16,15 +18,12 @@ namespace Epinova.InRiverConnector.EpiserverAdapter { public class CvlUpdater { - private readonly IConfiguration _config; private readonly CatalogDocumentFactory _catalogDocumentFactory; - private readonly EpiApi _epiApi; + private readonly IConfiguration _config; private readonly DocumentFileHelper _documentFileHelper; + private readonly EpiApi _epiApi; - public CvlUpdater(IConfiguration config, - CatalogDocumentFactory catalogDocumentFactory, - EpiApi epiApi, - DocumentFileHelper documentFileHelper) + public CvlUpdater(IConfiguration config, CatalogDocumentFactory catalogDocumentFactory, EpiApi epiApi, DocumentFileHelper documentFileHelper) { _config = config; _catalogDocumentFactory = catalogDocumentFactory; @@ -32,37 +31,37 @@ public CvlUpdater(IConfiguration config, _documentFileHelper = documentFileHelper; } - public ConnectorEvent CVLValueUpdated(Entity channel, string cvlId, string cvlValueKey) + public async Task CVLValueUpdatedAsync(Entity channel, string cvlId, string cvlValueKey) { - var connectorEvent = ConnectorEventHelper.InitiateEvent(_config, - ConnectorEventType.CVLValueUpdated, - $"CVL value updated, updating values in channel: {channel.DisplayName.Data}", 0); + ConnectorEvent connectorEvent = ConnectorEventHelper.InitiateEvent(_config, + ConnectorEventType.CVLValueUpdated, + $"CVL value updated, updating values in channel: {channel.DisplayName.Data}", 0); + + IEnumerable cvlFieldTypes = RemoteManager.ModelService.GetAllFieldTypes().Where(x => x.CVLId == cvlId); - var cvlFieldTypes = RemoteManager.ModelService.GetAllFieldTypes().Where(x => x.CVLId == cvlId); - - var criterias = cvlFieldTypes.Select(cvlFieldType => new Criteria + List criteria = cvlFieldTypes.Select(cvlFieldType => new Criteria { FieldTypeId = cvlFieldType.Id, Value = cvlValueKey, Operator = Operator.Equal }).ToList(); - var query = new Query { Criteria = criterias, Join = Join.Or }; - var entities = RemoteManager.DataService.Search(query, LoadLevel.DataOnly); + var query = new Query { Criteria = criteria, Join = Join.Or }; + List entities = RemoteManager.DataService.Search(query, LoadLevel.DataOnly); IntegrationLogger.Write(LogLevel.Debug, $"Found {entities.Count} entities with the CVL {cvlId} to update. Value-key to update: {cvlValueKey}."); - var updateDocument = _catalogDocumentFactory.CreateUpdateDocument(channel, entities); - var folderDateTime = DateTime.Now.ToString(Constants.PublicationFolderNameTimeComponent); + XDocument updateDocument = _catalogDocumentFactory.CreateUpdateDocument(channel, entities); + string folderDateTime = DateTime.Now.ToString(Constants.PublicationFolderNameTimeComponent); - var savedCatalogDocument = _documentFileHelper.SaveCatalogDocument(channel, updateDocument, folderDateTime); + string savedCatalogDocument = _documentFileHelper.SaveCatalogDocument(channel, updateDocument, folderDateTime); - _epiApi.ImportCatalog(savedCatalogDocument); + await _epiApi.ImportCatalogAsync(savedCatalogDocument); ConnectorEventHelper.UpdateEvent(connectorEvent, "Done sending Catalog.xml to EPiServer", 75); - _epiApi.NotifyEpiserverPostImport(Path.Combine(_config.PublicationsRootPath, folderDateTime, savedCatalogDocument)); + await _epiApi.NotifyEpiserverPostImportAsync(Path.Combine(_config.PublicationsRootPath, folderDateTime, savedCatalogDocument)); return connectorEvent; } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/EndpointCollection.cs b/src/EpiserverAdapter/EndpointCollection.cs index 663cae9..05c82f9 100644 --- a/src/EpiserverAdapter/EndpointCollection.cs +++ b/src/EpiserverAdapter/EndpointCollection.cs @@ -9,16 +9,16 @@ public EndpointCollection(string baseUrl) _baseUrl = baseUrl; } - public string ImportResources => _baseUrl + "ImportResources"; - public string IsImporting => _baseUrl + "IsImporting"; + public string CheckAndMoveNodeIfNeeded => _baseUrl + "MoveNodeToRootIfNeeded"; public string DeleteCatalog => _baseUrl + "DeleteCatalog"; - public string DeleteCatalogNode => _baseUrl + "DeleteCatalogNode"; public string DeleteCatalogEntry => _baseUrl + "DeleteCatalogEntry"; - public string CheckAndMoveNodeIfNeeded => _baseUrl + "MoveNodeToRootIfNeeded"; - public string ImportCatalogXml => _baseUrl + "ImportCatalogXml"; - public string ImportUpdateCompleted => _baseUrl + "ImportUpdateCompleted"; + public string DeleteCatalogNode => _baseUrl + "DeleteCatalogNode"; public string DeleteCompleted => _baseUrl + "DeleteCompleted"; - public string DeleteResource => _baseUrl + "DeleteResource"; public string DeleteLink => _baseUrl + "DeleteLink"; + public string DeleteResource => _baseUrl + "DeleteResource"; + public string ImportCatalogXml => _baseUrl + "ImportCatalogXml"; + public string ImportResources => _baseUrl + "ImportResources"; + public string ImportUpdateCompleted => _baseUrl + "ImportUpdateCompleted"; + public string IsImporting => _baseUrl + "IsImporting"; } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/EntityService.cs b/src/EpiserverAdapter/EntityService.cs index 4861115..75ee91f 100644 --- a/src/EpiserverAdapter/EntityService.cs +++ b/src/EpiserverAdapter/EntityService.cs @@ -9,8 +9,12 @@ namespace Epinova.InRiverConnector.EpiserverAdapter { public class EntityService : IEntityService { + private readonly Dictionary _cachedParentEntities; private readonly IConfiguration _config; private readonly EpiMappingHelper _mappingHelper; + private List _allResourceStructureEntities; + + private Dictionary> _cachedChannelNodeStructureEntities; /// /// Very simple local cache of all entities. FlushCache() empties the list. GetEntity should retrieve from this list if possible, to @@ -18,119 +22,121 @@ public class EntityService : IEntityService /// private List _cachedEntities; - private Dictionary> _cachedChannelNodeStructureEntities; - private List _allResourceStructureEntities; - private Dictionary _cachedParentEntities; - public EntityService(IConfiguration config, EpiMappingHelper mappingHelper) { _config = config; _mappingHelper = mappingHelper; - _cachedEntities = new List(); _cachedChannelNodeStructureEntities = new Dictionary>(); _cachedParentEntities = new Dictionary(); } - public Entity GetEntity(int id, LoadLevel loadLevel) + public void FlushCache() { - var existingEntity = _cachedEntities.FirstOrDefault(x => x.Id == id); - - if (existingEntity != null && loadLevel <= existingEntity.LoadLevel) - return existingEntity; - - var fetchedEntity = RemoteManager.DataService.GetEntity(id, loadLevel); - - if (existingEntity != null) - _cachedEntities.Remove(existingEntity); + _cachedEntities = new List(); + _cachedChannelNodeStructureEntities = new Dictionary>(); + _allResourceStructureEntities = null; + } - _cachedEntities.Add(fetchedEntity); + public List GetAllResourceLocations(int resourceEntityId) + { + if (_allResourceStructureEntities == null) + _allResourceStructureEntities = RemoteManager.ChannelService.GetAllChannelStructureEntitiesForType(_config.ChannelId, "Resource"); - return fetchedEntity; + return _allResourceStructureEntities.Where(x => x.EntityId == resourceEntityId).ToList(); } public List GetAllStructureEntitiesInChannel(List entityTypes) { - List result = new List(); + var result = new List(); foreach (EntityType entityType in entityTypes) { List response = RemoteManager.ChannelService.GetAllChannelStructureEntitiesForType(_config.ChannelId, entityType.Id); result.AddRange(response); } - return _config.ForceIncludeLinkedContent ? - result.ToList() : - result.Where(x => FilterLinkedContentNotBelongingToChannelNode(x, result)).ToList(); + return _config.ForceIncludeLinkedContent ? result.ToList() : result.Where(x => FilterLinkedContentNotBelongingToChannelNode(x, result)).ToList(); } - public List GetAllResourceLocations(int resourceEntityId) + public List GetChannelNodeStructureEntitiesInPath(string path) { - if(_allResourceStructureEntities == null) - _allResourceStructureEntities = RemoteManager.ChannelService.GetAllChannelStructureEntitiesForType(_config.ChannelId, "Resource"); + if (_cachedChannelNodeStructureEntities.ContainsKey(path)) + return _cachedChannelNodeStructureEntities[path]; - return _allResourceStructureEntities.Where(x => x.EntityId == resourceEntityId).ToList(); + List structureEntities = RemoteManager.ChannelService.GetAllChannelStructureEntitiesForTypeInPath(path, "ChannelNode"); + _cachedChannelNodeStructureEntities.Add(path, structureEntities); + return structureEntities; } - public List GetEntityInChannelWithParent(int channelId, int entityId, int parentId) + public List GetChildrenEntitiesInChannel(int entityId, string path) { var result = new List(); - var response = RemoteManager.ChannelService.GetAllStructureEntitiesForEntityWithParentInChannel(channelId, entityId, parentId); - if (response.Any()) + if (!String.IsNullOrEmpty(path)) { - result.AddRange(response); + List response = RemoteManager.ChannelService.GetChannelStructureChildrenFromPath(entityId, path); + if (response.Any()) + { + result.AddRange(response); + } } return result; } - public string GetTargetEntityPath(int targetEntityId, List channelEntities, int? parentId = null) + public Entity GetEntity(int id, LoadLevel loadLevel) { - StructureEntity targetStructureEntity = new StructureEntity(); + Entity existingEntity = _cachedEntities.FirstOrDefault(x => x.Id == id); - if (parentId == null) - { - targetStructureEntity = channelEntities.Find(i => i.EntityId.Equals(targetEntityId)); - } - else - { - targetStructureEntity = channelEntities.Find(i => i.EntityId.Equals(targetEntityId) && i.ParentId.Equals(parentId)); - } + if (existingEntity != null && loadLevel <= existingEntity.LoadLevel) + return existingEntity; + Entity fetchedEntity = RemoteManager.DataService.GetEntity(id, loadLevel); - string path = string.Empty; + if (existingEntity != null) + _cachedEntities.Remove(existingEntity); - if (targetStructureEntity != null) - { - path = targetStructureEntity.Path; - } + _cachedEntities.Add(fetchedEntity); - return path; + return fetchedEntity; } - public List GetChildrenEntitiesInChannel(int entityId, string path) + public List GetEntityInChannelWithParent(int channelId, int entityId, int parentId) { var result = new List(); - if (!string.IsNullOrEmpty(path)) + List response = RemoteManager.ChannelService.GetAllStructureEntitiesForEntityWithParentInChannel(channelId, entityId, parentId); + if (response.Any()) { - var response = RemoteManager.ChannelService.GetChannelStructureChildrenFromPath(entityId, path); - if (response.Any()) - { - result.AddRange(response); - } + result.AddRange(response); } return result; } - public List GetStructureEntitiesForEntityInChannel(int channelId, int entityId) + + public Entity GetParentProduct(StructureEntity itemStructureEntity) { - return RemoteManager.ChannelService.GetAllStructureEntitiesForEntityInChannel(channelId, entityId); + int entityId = itemStructureEntity.EntityId; + + if (_cachedParentEntities.ContainsKey(entityId)) + return _cachedParentEntities[entityId]; + + List inboundLinks = RemoteManager.DataService.GetInboundLinksForEntity(entityId); + Link relationLink = inboundLinks.OrderBy(x => x.Index) + .FirstOrDefault(x => _mappingHelper.IsRelation(x.LinkType)); + + if (relationLink == null) + return null; + + Entity parent = GetEntity(relationLink.Source.Id, LoadLevel.DataOnly); + _cachedParentEntities.Add(entityId, parent); + + return parent; } public StructureEntity GetParentStructureEntity(int channelId, int sourceEntityId, int targetEntityId, List channelEntities) { - var targetStructureEntity = channelEntities.Find(i => i.EntityId.Equals(targetEntityId) && i.ParentId.Equals(sourceEntityId)); - var structureEntities = RemoteManager.ChannelService.GetAllStructureEntitiesForEntityInChannel(channelId, sourceEntityId); + StructureEntity targetStructureEntity = channelEntities.Find(i => i.EntityId.Equals(targetEntityId) && i.ParentId.Equals(sourceEntityId)); + List structureEntities = RemoteManager.ChannelService.GetAllStructureEntitiesForEntityInChannel(channelId, sourceEntityId); if (targetStructureEntity == null || !structureEntities.Any()) { @@ -144,44 +150,35 @@ public StructureEntity GetParentStructureEntity(int channelId, int sourceEntityI return structureEntities.Find(i => i.Path.Equals(parentPath) && i.EntityId.Equals(sourceEntityId)); } - public List GetChannelNodeStructureEntitiesInPath(string path) + public List GetStructureEntitiesForEntityInChannel(int channelId, int entityId) { - if (_cachedChannelNodeStructureEntities.ContainsKey(path)) - return _cachedChannelNodeStructureEntities[path]; - - var structureEntities = RemoteManager.ChannelService.GetAllChannelStructureEntitiesForTypeInPath(path, "ChannelNode"); - _cachedChannelNodeStructureEntities.Add(path, structureEntities); - return structureEntities; + return RemoteManager.ChannelService.GetAllStructureEntitiesForEntityInChannel(channelId, entityId); } - - public Entity GetParentProduct(StructureEntity itemStructureEntity) + public string GetTargetEntityPath(int targetEntityId, List channelEntities, int? parentId = null) { - var entityId = itemStructureEntity.EntityId; - - if (_cachedParentEntities.ContainsKey(entityId)) - return _cachedParentEntities[entityId]; + StructureEntity targetStructureEntity = parentId == null + ? channelEntities.Find(i => i.EntityId.Equals(targetEntityId)) + : channelEntities.Find(i => i.EntityId.Equals(targetEntityId) && i.ParentId.Equals(parentId)); - var inboundLinks = RemoteManager.DataService.GetInboundLinksForEntity(entityId); - var relationLink = inboundLinks.OrderBy(x => x.Index) - .FirstOrDefault(x => _mappingHelper.IsRelation(x.LinkType)); + string path = String.Empty; - if (relationLink == null) - return null; - - var parent = GetEntity(relationLink.Source.Id, LoadLevel.DataOnly); - _cachedParentEntities.Add(entityId, parent); + if (targetStructureEntity != null) + { + path = targetStructureEntity.Path; + } - return parent; + return path; } - public void FlushCache() + private bool BelongsInChannel(StructureEntity arg) { - _cachedEntities = new List(); - _cachedChannelNodeStructureEntities = new Dictionary>(); - _allResourceStructureEntities = null; + bool isRelation = _mappingHelper.IsRelation(arg.LinkTypeIdFromParent); + bool isChannelNodeLink = _mappingHelper.IsChannelNodeLink(arg.LinkTypeIdFromParent); + + return isRelation || isChannelNodeLink; } - + /// /// Tells you whether or not a structure entity belongs in the channel, based on it's links. @@ -192,16 +189,8 @@ public void FlushCache() /// Everything in the channel. private bool FilterLinkedContentNotBelongingToChannelNode(StructureEntity structureEntity, List allStructureEntities) { - var sameEntityStructureEntities = allStructureEntities.Where(x => x.EntityId == structureEntity.EntityId); + IEnumerable sameEntityStructureEntities = allStructureEntities.Where(x => x.EntityId == structureEntity.EntityId); return sameEntityStructureEntities.Any(BelongsInChannel); } - - private bool BelongsInChannel(StructureEntity arg) - { - var isRelation = _mappingHelper.IsRelation(arg.LinkTypeIdFromParent); - var isChannelNodeLink = _mappingHelper.IsChannelNodeLink(arg.LinkTypeIdFromParent); - - return isRelation || isChannelNodeLink; - } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/Enums/CVLDataMode.cs b/src/EpiserverAdapter/Enums/CVLDataMode.cs index b18822e..36b86de 100644 --- a/src/EpiserverAdapter/Enums/CVLDataMode.cs +++ b/src/EpiserverAdapter/Enums/CVLDataMode.cs @@ -7,4 +7,4 @@ public enum CVLDataMode Values, KeysAndValues } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/EpiserverAdapter.cs b/src/EpiserverAdapter/EpiserverAdapter.cs index e9e2cf9..7e455d7 100644 --- a/src/EpiserverAdapter/EpiserverAdapter.cs +++ b/src/EpiserverAdapter/EpiserverAdapter.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Reflection; +using System.Threading.Tasks; using Epinova.InRiverConnector.EpiserverAdapter.Communication; using Epinova.InRiverConnector.EpiserverAdapter.Helpers; using Epinova.InRiverConnector.EpiserverAdapter.XmlFactories; @@ -17,20 +18,142 @@ namespace Epinova.InRiverConnector.EpiserverAdapter { public class EpiserverAdapter : ServerListener, IOutboundConnector, IChannelListener, ICVLListener { - private bool _started; - private IConfiguration _config; - private EpiApi _epiApi; - private CatalogElementFactory _catalogElementFactory; + private CatalogCodeGenerator _catalogCodeGenerator; private CatalogDocumentFactory _catalogDocumentFactory; + private CatalogElementFactory _catalogElementFactory; private ChannelHelper _channelHelper; - private ResourceElementFactory _resourceElementFactory; - private EpiMappingHelper _epiMappingHelper; - private CatalogCodeGenerator _catalogCodeGenerator; - private ChannelPublisher _publisher; - private PimFieldAdapter _pimFieldAdapter; - private IEntityService _entityService; + private IConfiguration _config; private CvlUpdater _cvlUpdater; private DocumentFileHelper _documentFileHelper; + private IEntityService _entityService; + private EpiApi _epiApi; + private EpiMappingHelper _epiMappingHelper; + private PimFieldAdapter _pimFieldAdapter; + private ChannelPublisher _publisher; + private ResourceElementFactory _resourceElementFactory; + + public new bool IsStarted { get; private set; } + + public void AssortmentCopiedInChannel(int channelId, int assortmentId, int targetId, string targetType) + { + } + + public void ChannelEntityAdded(int channelId, int entityId) + { + DoWithInitCheck(channelId, ConnectorEventType.ChannelEntityAdded, channel => _publisher.ChannelEntityAddedAsync(channel, entityId)); + } + + public void ChannelEntityDeleted(int channelId, Entity deletedEntity) + { + DoWithInitCheck(channelId, ConnectorEventType.ChannelEntityDeleted, channel => _publisher.ChannelEntityDeletedAsync(channel, deletedEntity)); + } + + public void ChannelEntityFieldSetUpdated(int channelId, int entityId, string fieldSetId) + { + ChannelEntityUpdated(channelId, entityId, null); + } + + public void ChannelEntitySpecificationFieldAdded(int channelId, int entityId, string fieldName) + { + ChannelEntityUpdated(channelId, entityId, null); + } + + public void ChannelEntitySpecificationFieldUpdated(int channelId, int entityId, string fieldName) + { + ChannelEntityUpdated(channelId, entityId, null); + } + + public void ChannelEntityUpdated(int channelId, int entityId, string data) + { + DoWithInitCheck(channelId, ConnectorEventType.ChannelEntityUpdated, channel => + { + if (channel.Id == entityId) + { + ConnectorEvent connectorEvent = ConnectorEventHelper.InitiateEvent(_config, ConnectorEventType.ChannelEntityUpdated, "Updated Entity is the Channel, no action required", 100); + return connectorEvent; + } + + return AsyncHelper.RunSync(() => _publisher.ChannelEntityUpdatedAsync(channel, entityId, data)); + }); + } + + public void ChannelLinkAdded(int channelId, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) + { + DoWithInitCheck(channelId, ConnectorEventType.ChannelLinkAdded, channel => _publisher.ChannelLinkAddedAsync(channel, sourceEntityId, targetEntityId, linkTypeId, linkEntityId)); + } + + public void ChannelLinkDeleted(int channelId, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) + { + DoWithInitCheck(channelId, ConnectorEventType.ChannelLinkDeleted, + channel => _publisher.ChannelLinkDeletedAsync(channel, sourceEntityId, targetEntityId, linkTypeId, linkEntityId) + ); + } + + public void ChannelLinkUpdated(int channelId, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) + { + DoWithInitCheck(channelId, ConnectorEventType.ChannelLinkUpdated, channel => + _publisher.ChannelLinkUpdatedAsync(channel, sourceEntityId, targetEntityId, linkTypeId, linkEntityId) + ); + } + + public void Publish(int channelId) + { + DoWithInitCheck(channelId, ConnectorEventType.Publish, channelEntity => _publisher.PublishAsync(channelEntity)); + } + + public void Synchronize(int channelId) + { + } + + public void UnPublish(int channelId) + { + if (channelId != _config.ChannelId) + return; + + IntegrationLogger.Write(LogLevel.Information, $"Unpublish on channel: {channelId} called. No action taken."); + } + + public void CVLValueCreated(string cvlId, string cvlValueKey) + { + } + + public void CVLValueDeleted(string cvlId, string cvlValueKey) + { + } + + public void CVLValueDeletedAll(string cvlId) + { + } + + public void CVLValueUpdated(string cvlId, string cvlValueKey) + { + DoWithInitCheck(_config.ChannelId, ConnectorEventType.CVLValueUpdated, channelEntity => _cvlUpdater.CVLValueUpdatedAsync(channelEntity, cvlId, cvlValueKey)); + } + + public new void InitConfigurationSettings() + { + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.PublishFolder, ConfigDefaults.PublishFolder); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ResourcesPublishFolder, ConfigDefaults.ResourcesPublishFolder); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ResourceConfiguration, ConfigDefaults.ResourceConfiguration); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.LanguageMapping, ConfigDefaults.LanguageMapping); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ItemToSkus, ConfigDefaults.ItemToSkus); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.CvlData, ConfigDefaults.CvlData); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.BundleTypes, String.Empty); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.PackageTypes, String.Empty); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.DynamicPackageTypes, String.Empty); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ChannelId, "123"); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.EpiCodeFields, String.Empty); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ExcludeFields, String.Empty); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.EpiNameFields, String.Empty); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.UseThreeLevelsInCommerce, ConfigDefaults.UseThreeLevelsinCommerce); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.HttpPostUrl, String.Empty); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.EpiEndpoint, ConfigDefaults.EpiEndpoint); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.EpiApiKey, ConfigDefaults.EpiApiKey); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.EpiTimeout, ConfigDefaults.EpiTimeout); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ExportEntities, ConfigDefaults.ExportEntities); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.BatchSize, String.Empty); + ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ForceIncludeLinkedContent, ConfigDefaults.ForceIncludeLinkedContent); + } public new void Start() { @@ -45,7 +168,7 @@ public class EpiserverAdapter : ServerListener, IOutboundConnector, IChannelList Entity channel = RemoteManager.DataService.GetEntity(_config.ChannelId, LoadLevel.Shallow); if (channel == null || channel.EntityType.Id != "Channel") { - _started = false; + IsStarted = false; ConnectorEventHelper.UpdateEvent(startEvent, "Channel id is not valid: Entity with given ID is not a channel, or doesn't exist. Unable to start", -1, true); return; } @@ -54,32 +177,32 @@ public class EpiserverAdapter : ServerListener, IOutboundConnector, IChannelList _epiMappingHelper = new EpiMappingHelper(_config, _pimFieldAdapter); _entityService = new EntityService(_config, _epiMappingHelper); _catalogCodeGenerator = new CatalogCodeGenerator(_config, _entityService); - _epiApi = new EpiApi(_config, _catalogCodeGenerator, _pimFieldAdapter); + _epiApi = new EpiApi(_config, _catalogCodeGenerator); _catalogElementFactory = new CatalogElementFactory(_config, _epiMappingHelper, _catalogCodeGenerator, _pimFieldAdapter); _channelHelper = new ChannelHelper(_config, _entityService); _catalogDocumentFactory = new CatalogDocumentFactory(_config, _epiApi, _catalogElementFactory, _epiMappingHelper, _channelHelper, _catalogCodeGenerator, _entityService); _resourceElementFactory = new ResourceElementFactory(_catalogElementFactory, _epiMappingHelper, _catalogCodeGenerator, _config, _entityService); - + _documentFileHelper = new DocumentFileHelper(_config, _channelHelper); _cvlUpdater = new CvlUpdater(_config, _catalogDocumentFactory, _epiApi, _documentFileHelper); - _publisher = new ChannelPublisher(_config, - _catalogDocumentFactory, - _catalogElementFactory, - _resourceElementFactory, - _epiApi, - _epiMappingHelper, - _documentFileHelper, - _pimFieldAdapter, - _entityService, - _catalogCodeGenerator); + _publisher = new ChannelPublisher(_config, + _catalogDocumentFactory, + _catalogElementFactory, + _resourceElementFactory, + _epiApi, + _epiMappingHelper, + _documentFileHelper, + _pimFieldAdapter, + _entityService, + _catalogCodeGenerator); AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainAssemblyResolve; InitConnector(); base.Start(); - _started = true; + IsStarted = true; ConnectorEventHelper.UpdateEvent(startEvent, "Connector has started", 100); } catch (Exception ex) @@ -93,8 +216,8 @@ public class EpiserverAdapter : ServerListener, IOutboundConnector, IChannelList public new void Stop() { base.Stop(); - var connectorEvent = ConnectorEventHelper.InitiateEvent(_config, ConnectorEventType.Stop, "Connector is stopping", 0); - _started = false; + ConnectorEvent connectorEvent = ConnectorEventHelper.InitiateEvent(_config, ConnectorEventType.Stop, "Connector is stopping", 0); + IsStarted = false; _epiApi = null; _catalogElementFactory = null; _catalogDocumentFactory = null; @@ -111,139 +234,45 @@ public class EpiserverAdapter : ServerListener, IOutboundConnector, IChannelList ConnectorEventHelper.UpdateEvent(connectorEvent, "Connector has stopped.", 100); } - public new void InitConfigurationSettings() - { - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.PublishFolder, ConfigDefaults.PublishFolder); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ResourcesPublishFolder, ConfigDefaults.ResourcesPublishFolder); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ResourceConfiguration, ConfigDefaults.ResourceConfiguration); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.LanguageMapping, ConfigDefaults.LanguageMapping); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ItemToSkus, ConfigDefaults.ItemToSkus); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.CvlData, ConfigDefaults.CvlData); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.BundleTypes, string.Empty); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.PackageTypes, string.Empty); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.DynamicPackageTypes, string.Empty); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ChannelId, "123"); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.EpiCodeFields, string.Empty); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ExcludeFields, string.Empty); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.EpiNameFields, string.Empty); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.UseThreeLevelsInCommerce, ConfigDefaults.UseThreeLevelsinCommerce); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.HttpPostUrl, string.Empty); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.EpiEndpoint, ConfigDefaults.EpiEndpoint); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.EpiApiKey, ConfigDefaults.EpiApiKey); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.EpiTimeout, ConfigDefaults.EpiTimeout); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ExportEntities, ConfigDefaults.ExportEntities); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.BatchSize, string.Empty); - ConfigurationManager.Instance.SetConnectorSetting(Id, ConfigKeys.ForceIncludeLinkedContent, ConfigDefaults.ForceIncludeLinkedContent); - } - - public new bool IsStarted => _started; - - public void Publish(int channelId) - { - DoWithInitCheck(channelId, ConnectorEventType.Publish, channelEntity => _publisher.Publish(channelEntity)); - } - - public void UnPublish(int channelId) + private Assembly CurrentDomainAssemblyResolve(object sender, ResolveEventArgs args) { - if (channelId != _config.ChannelId) - return; + string folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + if (folderPath == null) + return null; - IntegrationLogger.Write(LogLevel.Information, $"Unpublish on channel: {channelId} called. No action taken."); - } + int ix = folderPath.LastIndexOf("\\", StringComparison.Ordinal); + if (ix == -1) + { + return null; + } - public void Synchronize(int channelId) - { - } + folderPath = folderPath.Substring(0, ix); + string assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); - public void ChannelEntityAdded(int channelId, int entityId) - { - DoWithInitCheck(channelId, ConnectorEventType.ChannelEntityAdded, channel => _publisher.ChannelEntityAdded(channel, entityId)); - } - - public void ChannelEntityUpdated(int channelId, int entityId, string data) - { - DoWithInitCheck(channelId, ConnectorEventType.ChannelEntityUpdated, channel => + if (File.Exists(assemblyPath) == false) { - if (channel.Id == entityId) + assemblyPath = Path.Combine(folderPath + "\\OutboundConnectors\\", new AssemblyName(args.Name).Name + ".dll"); + if (File.Exists(assemblyPath) == false) { - var connectorEvent = ConnectorEventHelper.InitiateEvent(_config, ConnectorEventType.ChannelEntityUpdated, "Updated Entity is the Channel, no action required", 100); - return connectorEvent; + return null; } + } - return _publisher.ChannelEntityUpdated(channel, entityId, data); - }); - } - - public void ChannelEntityDeleted(int channelId, Entity deletedEntity) - { - DoWithInitCheck(channelId, ConnectorEventType.ChannelEntityDeleted, channel => _publisher.ChannelEntityDeleted(channel, deletedEntity)); - } - - public void ChannelEntityFieldSetUpdated(int channelId, int entityId, string fieldSetId) - { - ChannelEntityUpdated(channelId, entityId, null); - } - - public void ChannelEntitySpecificationFieldAdded(int channelId, int entityId, string fieldName) - { - ChannelEntityUpdated(channelId, entityId, null); - } - - public void ChannelEntitySpecificationFieldUpdated(int channelId, int entityId, string fieldName) - { - ChannelEntityUpdated(channelId, entityId, null); - } - - public void ChannelLinkAdded(int channelId, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) - { - DoWithInitCheck(channelId, ConnectorEventType.ChannelLinkAdded, - channel => _publisher.ChannelLinkAdded(channel, sourceEntityId, targetEntityId, linkTypeId, linkEntityId)); - } - - public void ChannelLinkDeleted(int channelId, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) - { - DoWithInitCheck(channelId, ConnectorEventType.ChannelLinkDeleted, - channel => _publisher.ChannelLinkDeleted(channel, sourceEntityId, targetEntityId, linkTypeId, linkEntityId) - ); - } - - public void ChannelLinkUpdated(int channelId, int sourceEntityId, int targetEntityId, string linkTypeId, int? linkEntityId) - { - DoWithInitCheck(channelId, ConnectorEventType.ChannelLinkUpdated, channel => - _publisher.ChannelLinkUpdated(channel, sourceEntityId, targetEntityId, linkTypeId, linkEntityId) - ); + Assembly assembly = Assembly.LoadFrom(assemblyPath); + return assembly; } - public void AssortmentCopiedInChannel(int channelId, int assortmentId, int targetId, string targetType) + private void DoWithInitCheck(int channelId, ConnectorEventType eventType, Func> thingsToDo) { - + DoWithInitCheck(channelId, eventType, x => AsyncHelper.RunSync(() => thingsToDo(x))); } - private void InitConnector() - { - try - { - var directoryInfo = Directory.CreateDirectory(_config.PublicationsRootPath); - - var accessCheckerFileName = "Access_check"; - var filename = Path.Combine(directoryInfo.FullName, accessCheckerFileName); - - File.WriteAllText(filename, "Access-checker"); - File.Delete(filename); - } - catch (Exception ex) - { - IntegrationLogger.Write(LogLevel.Error, $"Attempt to write to {_config.PublicationsRootPath} failed.", ex); - throw; - } - } - private void DoWithInitCheck(int channelId, ConnectorEventType eventType, Func thingsToDo) { if (channelId != _config.ChannelId) return; - var channelEntity = _channelHelper.InitiateChannelConfiguration(channelId); + Entity channelEntity = _channelHelper.InitiateChannelConfiguration(channelId); if (channelEntity == null) { ConnectorEventHelper.InitiateEvent(_config, eventType, $"Failed perform {eventType}. Could not find the channel.", -1, true); @@ -252,12 +281,12 @@ private void DoWithInitCheck(int channelId, ConnectorEventType eventType, Func _cvlUpdater.CVLValueUpdated(channelEntity, cvlId, cvlValueKey)); - } - - public void CVLValueDeleted(string cvlId, string cvlValueKey) - { - } - - public void CVLValueDeletedAll(string cvlId) - { - } - - private Assembly CurrentDomainAssemblyResolve(object sender, ResolveEventArgs args) + private void InitConnector() { - string folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - if (folderPath == null) - return null; - - int ix = folderPath.LastIndexOf("\\", StringComparison.Ordinal); - if (ix == -1) + try { - return null; - } + DirectoryInfo directoryInfo = Directory.CreateDirectory(_config.PublicationsRootPath); - folderPath = folderPath.Substring(0, ix); - string assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); + const string accessCheckerFileName = "Access_check"; + string filename = Path.Combine(directoryInfo.FullName, accessCheckerFileName); - if (File.Exists(assemblyPath) == false) + File.WriteAllText(filename, "Access-checker"); + File.Delete(filename); + } + catch (Exception ex) { - assemblyPath = Path.Combine(folderPath + "\\OutboundConnectors\\", new AssemblyName(args.Name).Name + ".dll"); - if (File.Exists(assemblyPath) == false) - { - return null; - } + IntegrationLogger.Write(LogLevel.Error, $"Attempt to write to {_config.PublicationsRootPath} failed.", ex); + throw; } - - Assembly assembly = Assembly.LoadFrom(assemblyPath); - return assembly; } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/EpiserverAdapter.csproj b/src/EpiserverAdapter/EpiserverAdapter.csproj index 66e9ebf..b3416d5 100644 --- a/src/EpiserverAdapter/EpiserverAdapter.csproj +++ b/src/EpiserverAdapter/EpiserverAdapter.csproj @@ -44,8 +44,8 @@ - - ..\..\lib\System.Net.Http.Formatting.dll + + ..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll @@ -58,6 +58,7 @@ + @@ -102,11 +103,4 @@ - \ No newline at end of file diff --git a/src/EpiserverAdapter/Extensions.cs b/src/EpiserverAdapter/Extensions.cs index 50c072d..1934945 100644 --- a/src/EpiserverAdapter/Extensions.cs +++ b/src/EpiserverAdapter/Extensions.cs @@ -4,24 +4,24 @@ namespace Epinova.InRiverConnector.EpiserverAdapter { internal static class Extensions { - internal static bool IsItem(this StructureEntity structureEntity) - { - return structureEntity.Type == "Item"; - } - internal static bool IsChannelNode(this StructureEntity structureEntity) { return structureEntity.Type == "ChannelNode"; } - internal static bool SourceEntityTypeIsChannelNode(this LinkType linkType) + internal static bool IsItem(this StructureEntity structureEntity) { - return linkType.SourceEntityTypeId == "ChannelNode"; + return structureEntity.Type == "Item"; } internal static bool IsProductItemLink(this LinkType linkType) { return linkType.SourceEntityTypeId == "Product" && linkType.TargetEntityTypeId == "Item"; } + + internal static bool SourceEntityTypeIsChannelNode(this LinkType linkType) + { + return linkType.SourceEntityTypeId == "ChannelNode"; + } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/FieldNames.cs b/src/EpiserverAdapter/FieldNames.cs index 7fa556e..fb3df3e 100644 --- a/src/EpiserverAdapter/FieldNames.cs +++ b/src/EpiserverAdapter/FieldNames.cs @@ -2,10 +2,10 @@ { public static class FieldNames { - public static string ResourceMimeType = "ResourceMimeType"; public static string EPiCommonField = "EPiMetaFieldName"; - public static string SKUFieldName = "SKUs"; - public static string SKUData = "Data"; public static string ResourceFileId = "ResourceFileId"; + public static string ResourceMimeType = "ResourceMimeType"; + public static string SKUData = "Data"; + public static string SKUFieldName = "SKUs"; } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/Helpers/ChannelHelper.cs b/src/EpiserverAdapter/Helpers/ChannelHelper.cs index 9a65ce3..cdea339 100644 --- a/src/EpiserverAdapter/Helpers/ChannelHelper.cs +++ b/src/EpiserverAdapter/Helpers/ChannelHelper.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Security.Cryptography; @@ -21,18 +22,15 @@ public ChannelHelper(IConfiguration config, IEntityService entityService) _entityService = entityService; } - - public Entity InitiateChannelConfiguration(int channelId) + public string GetChannelDefaultWeightBase(Entity channel) { - Entity channel = _entityService.GetEntity(channelId, LoadLevel.DataOnly); - if (channel == null) + Field defaultWeightBaseField = channel.Fields.FirstOrDefault(f => f.FieldType.Id.ToLower().Contains("channeldefaultweightbase")); + if (defaultWeightBaseField == null || defaultWeightBaseField.IsEmpty()) { - IntegrationLogger.Write(LogLevel.Error, "Could not find channel"); - return null; + return "lbs"; } - UpdateChannelSettings(channel); - return channel; + return defaultWeightBaseField.Data.ToString(); } public Guid GetChannelGuid(Entity channel) @@ -43,7 +41,7 @@ public Guid GetChannelGuid(Entity channel) { if (channel.DisplayName.FieldType.DataType.Equals(DataType.LocaleString)) { - var cultureInfo = _config.LanguageMapping[_config.ChannelDefaultLanguage]; + CultureInfo cultureInfo = _config.LanguageMapping[_config.ChannelDefaultLanguage]; value = ((LocaleString)channel.DisplayName.Data)[cultureInfo]; } else @@ -51,7 +49,7 @@ public Guid GetChannelGuid(Entity channel) value = channel.DisplayName.Data.ToString(); } - if (string.IsNullOrEmpty(value)) + if (String.IsNullOrEmpty(value)) { value = channel.Id.ToString(CultureInfo.InvariantCulture); } @@ -62,20 +60,6 @@ public Guid GetChannelGuid(Entity channel) return new Guid(data); } - public Entity GetParentChannelNode(StructureEntity structureEntity) - { - var channelNodesInPath = _entityService.GetChannelNodeStructureEntitiesInPath(structureEntity.Path); - var entity = channelNodesInPath.LastOrDefault(); - return entity != null ? _entityService.GetEntity(entity.EntityId, LoadLevel.DataOnly) : null; - } - - public bool ItemHasParentInChannel(StructureEntity itemStructureEntity) - { - var parentProduct = _entityService.GetParentProduct(itemStructureEntity); - var parentEntityStructureEntities = RemoteManager.ChannelService.GetAllStructureEntitiesForEntityInChannel(_config.ChannelId, parentProduct.Id); - return parentEntityStructureEntities != null && parentEntityStructureEntities.Any(); - } - public string GetChannelIdentifier(Entity channelEntity) { string channelIdentifier = channelEntity.Id.ToString(CultureInfo.InvariantCulture); @@ -86,28 +70,33 @@ public string GetChannelIdentifier(Entity channelEntity) return channelIdentifier; } - - private string GetChannelPrefix(Entity channel) + public Entity GetParentChannelNode(StructureEntity structureEntity) { - Field channelPrefixField = channel.Fields.FirstOrDefault(f => f.FieldType.Id.ToLower().Contains("channelprefix")); - if (channelPrefixField == null || channelPrefixField.IsEmpty()) - { - return string.Empty; - } - - return channelPrefixField.Data.ToString(); + List channelNodesInPath = _entityService.GetChannelNodeStructureEntitiesInPath(structureEntity.Path); + StructureEntity entity = channelNodesInPath.LastOrDefault(); + return entity != null ? _entityService.GetEntity(entity.EntityId, LoadLevel.DataOnly) : null; } - private CultureInfo GetChannelDefaultLanguage(Entity channel) + + public Entity InitiateChannelConfiguration(int channelId) { - Field defaultLanguageField = channel.Fields.FirstOrDefault(f => f.FieldType.Id.ToLower().Contains("channeldefaultlanguage")); - if (defaultLanguageField == null || defaultLanguageField.IsEmpty()) + Entity channel = _entityService.GetEntity(channelId, LoadLevel.DataOnly); + if (channel == null) { - return new CultureInfo("en-us"); + IntegrationLogger.Write(LogLevel.Error, "Could not find channel"); + return null; } - return new CultureInfo(defaultLanguageField.Data.ToString()); + UpdateChannelSettings(channel); + return channel; + } + + public bool ItemHasParentInChannel(StructureEntity itemStructureEntity) + { + Entity parentProduct = _entityService.GetParentProduct(itemStructureEntity); + List parentEntityStructureEntities = RemoteManager.ChannelService.GetAllStructureEntitiesForEntityInChannel(_config.ChannelId, parentProduct.Id); + return parentEntityStructureEntities != null && parentEntityStructureEntities.Any(); } private string GetChannelDefaultCurrency(Entity channel) @@ -121,15 +110,27 @@ private string GetChannelDefaultCurrency(Entity channel) return defaultCurrencyField.Data.ToString(); } - public string GetChannelDefaultWeightBase(Entity channel) + private CultureInfo GetChannelDefaultLanguage(Entity channel) { - Field defaultWeightBaseField = channel.Fields.FirstOrDefault(f => f.FieldType.Id.ToLower().Contains("channeldefaultweightbase")); - if (defaultWeightBaseField == null || defaultWeightBaseField.IsEmpty()) + Field defaultLanguageField = channel.Fields.FirstOrDefault(f => f.FieldType.Id.ToLower().Contains("channeldefaultlanguage")); + if (defaultLanguageField == null || defaultLanguageField.IsEmpty()) { - return "lbs"; + return new CultureInfo("en-us"); } - return defaultWeightBaseField.Data.ToString(); + return new CultureInfo(defaultLanguageField.Data.ToString()); + } + + + private string GetChannelPrefix(Entity channel) + { + Field channelPrefixField = channel.Fields.FirstOrDefault(f => f.FieldType.Id.ToLower().Contains("channelprefix")); + if (channelPrefixField == null || channelPrefixField.IsEmpty()) + { + return String.Empty; + } + + return channelPrefixField.Data.ToString(); } private void UpdateChannelSettings(Entity channel) @@ -140,4 +141,4 @@ private void UpdateChannelSettings(Entity channel) _config.ChannelIdPrefix = GetChannelPrefix(channel); } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/Helpers/ConnectorEventHelper.cs b/src/EpiserverAdapter/Helpers/ConnectorEventHelper.cs index 192c61f..d46ea30 100644 --- a/src/EpiserverAdapter/Helpers/ConnectorEventHelper.cs +++ b/src/EpiserverAdapter/Helpers/ConnectorEventHelper.cs @@ -76,4 +76,4 @@ internal static ConnectorEvent UpdateEvent(ConnectorEvent connectorEvent, string return connectorEvent; } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/Helpers/DocumentFileHelper.cs b/src/EpiserverAdapter/Helpers/DocumentFileHelper.cs index f6459b1..073b5e2 100644 --- a/src/EpiserverAdapter/Helpers/DocumentFileHelper.cs +++ b/src/EpiserverAdapter/Helpers/DocumentFileHelper.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.IO.Packaging; using System.Linq; using System.Xml.Linq; using inRiver.Integration.Logging; @@ -13,8 +12,8 @@ namespace Epinova.InRiverConnector.EpiserverAdapter.Helpers { public class DocumentFileHelper { - private readonly IConfiguration _config; private readonly ChannelHelper _channelHelper; + private readonly IConfiguration _config; public DocumentFileHelper(IConfiguration config, ChannelHelper channelHelper) { @@ -22,23 +21,21 @@ public DocumentFileHelper(IConfiguration config, ChannelHelper channelHelper) _channelHelper = channelHelper; } - public string SaveDocument(XDocument doc, string path) + public static void CopyStream(FileStream inputStream, Stream outputStream) { - if (!Directory.Exists(path)) + const long maxBufferSize = 4096; + long bufferSize = inputStream.Length < maxBufferSize ? inputStream.Length : maxBufferSize; + var buffer = new byte[bufferSize]; + int bytesRead; + while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) != 0) { - Directory.CreateDirectory(path); + outputStream.Write(buffer, 0, bytesRead); } - - var filePath = Path.Combine(path, Constants.ResourceExportFilename); - - IntegrationLogger.Write(LogLevel.Information, $"Saving document to path {filePath}."); - doc.Save(filePath); - return filePath; } public string SaveCatalogDocument(Entity channel, XDocument doc, string folderNameTimestampComponent) { - var dirPath = Path.Combine(_config.PublicationsRootPath, folderNameTimestampComponent); + string dirPath = Path.Combine(_config.PublicationsRootPath, folderNameTimestampComponent); if (!Directory.Exists(dirPath)) { @@ -55,75 +52,42 @@ public string SaveCatalogDocument(Entity channel, XDocument doc, string folderNa IntegrationLogger.Write(LogLevel.Error, "Fail to verify the document: ", exception); } - var filePath = Path.Combine(dirPath, Constants.CatalogExportFilename); + string filePath = Path.Combine(dirPath, Constants.CatalogExportFilename); - var channelIdentifier = _channelHelper.GetChannelIdentifier(channel); + string channelIdentifier = _channelHelper.GetChannelIdentifier(channel); IntegrationLogger.Write(LogLevel.Information, $"Saving verified document to path {filePath} for channel: {channelIdentifier}"); doc.Save(filePath); return filePath; } - - public static void CopyStream(FileStream inputStream, Stream outputStream) - { - const long MaxbuffertSize = 4096; - long bufferSize = inputStream.Length < MaxbuffertSize ? inputStream.Length : MaxbuffertSize; - byte[] buffer = new byte[bufferSize]; - int bytesRead; - while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) != 0) - { - outputStream.Write(buffer, 0, bytesRead); - } - } - - private XDocument VerifyAndCorrectDocument(XDocument doc) - { - var unwantedEntityTypes = CreateUnwantedEntityTypeList(); - XDocument result = new XDocument(doc); - XElement root = result.Root; - if (root == null) - { - throw new Exception("Can't verify the Catalog.cml as it's empty."); - } - var entryElements = root.Descendants("Entry"); - var codesToBeRemoved = new List(); - foreach (XElement entryElement in entryElements) + public string SaveDocument(XDocument doc, string path) + { + if (!Directory.Exists(path)) { - var code = entryElement.Elements("Code").First().Value; - var metaClassName = entryElement.Elements("MetaData") - .Elements("MetaClass") - .Elements("Name") - .First().Value; - - if (!unwantedEntityTypes.Contains(metaClassName)) - continue; - - IntegrationLogger.Write(LogLevel.Debug, $"Code {code} will be removed as it has wrong metaclass name ({metaClassName})"); - codesToBeRemoved.Add(code); + Directory.CreateDirectory(path); } - foreach (var code in codesToBeRemoved) - { - root.Descendants("Entry").Where(x => x.Element("Code")?.Value == code).Remove(); - } + string filePath = Path.Combine(path, Constants.ResourceExportFilename); - return result; + IntegrationLogger.Write(LogLevel.Information, $"Saving document to path {filePath}."); + doc.Save(filePath); + return filePath; } private List CreateUnwantedEntityTypeList() { - List typeIds = new List - { - "Channel", - "Assortment", - "Resource", - "Task", - "Section", - "Publication" - }; - - List result = new List(); + var typeIds = new List + { + "Channel", + "Assortment", + "Resource", + "Task", + "Section", + "Publication" + }; + + var result = new List(); foreach (string typeId in typeIds) { List
fieldSets = RemoteManager.ModelService.GetFieldSetsForEntityType(typeId); @@ -149,5 +113,40 @@ private List CreateUnwantedEntityTypeList() return result; } + + private XDocument VerifyAndCorrectDocument(XDocument doc) + { + List unwantedEntityTypes = CreateUnwantedEntityTypeList(); + var result = new XDocument(doc); + XElement root = result.Root; + if (root == null) + { + throw new Exception("Can't verify the Catalog.cml as it's empty."); + } + + IEnumerable entryElements = root.Descendants("Entry"); + var codesToBeRemoved = new List(); + foreach (XElement entryElement in entryElements) + { + string code = entryElement.Elements("Code").First().Value; + string metaClassName = entryElement.Elements("MetaData") + .Elements("MetaClass") + .Elements("Name") + .First().Value; + + if (!unwantedEntityTypes.Contains(metaClassName)) + continue; + + IntegrationLogger.Write(LogLevel.Debug, $"Code {code} will be removed as it has wrong metaclass name ({metaClassName})"); + codesToBeRemoved.Add(code); + } + + foreach (string code in codesToBeRemoved) + { + root.Descendants("Entry").Where(x => x.Element("Code")?.Value == code).Remove(); + } + + return result; + } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/Helpers/EpiMappingHelper.cs b/src/EpiserverAdapter/Helpers/EpiMappingHelper.cs index d3c7963..a29abd7 100644 --- a/src/EpiserverAdapter/Helpers/EpiMappingHelper.cs +++ b/src/EpiserverAdapter/Helpers/EpiMappingHelper.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using inRiver.Integration.Logging; using inRiver.Remoting; @@ -75,9 +76,9 @@ public string GetEntryType(string entityTypeId) public string GetEpiserverDataType(FieldType fieldType) { - string type = string.Empty; + string type = String.Empty; - if (fieldType == null || string.IsNullOrEmpty(fieldType.DataType)) + if (fieldType == null || String.IsNullOrEmpty(fieldType.DataType)) { return type; } @@ -110,25 +111,11 @@ public string GetEpiserverDataType(FieldType fieldType) { if (fieldType.Settings.ContainsKey("AdvancedTextObject")) { - if (fieldType.Settings["AdvancedTextObject"] == "1") - { - type = "LongHtmlString"; - } - else - { - type = "LongString"; - } + type = fieldType.Settings["AdvancedTextObject"] == "1" ? "LongHtmlString" : "LongString"; } else if (fieldType.Settings.ContainsKey("EPiDataType")) { - if (fieldType.Settings["EPiDataType"] == "ShortString") - { - type = "ShortString"; - } - else - { - type = "LongString"; - } + type = fieldType.Settings["EPiDataType"] == "ShortString" ? "ShortString" : "LongString"; } else { @@ -139,14 +126,7 @@ public string GetEpiserverDataType(FieldType fieldType) { if (fieldType.Settings.ContainsKey("EPiDataType")) { - if (fieldType.Settings["EPiDataType"] == "ShortString") - { - type = "ShortString"; - } - else - { - type = "LongString"; - } + type = fieldType.Settings["EPiDataType"] == "ShortString" ? "ShortString" : "LongString"; } else { @@ -157,14 +137,7 @@ public string GetEpiserverDataType(FieldType fieldType) { if (fieldType.Settings.ContainsKey("EPiDataType")) { - if (fieldType.Settings["EPiDataType"] == "ShortString") - { - type = "ShortString"; - } - else - { - type = "LongString"; - } + type = fieldType.Settings["EPiDataType"] == "ShortString" ? "ShortString" : "LongString"; } else { @@ -181,7 +154,7 @@ public string GetEpiserverFieldName(FieldType fieldType) if (fieldType.Settings != null && fieldType.Settings.ContainsKey(FieldNames.EPiCommonField) && - !string.IsNullOrEmpty(fieldType.Settings[FieldNames.EPiCommonField])) + !String.IsNullOrEmpty(fieldType.Settings[FieldNames.EPiCommonField])) { name = fieldType.Settings[FieldNames.EPiCommonField]; } @@ -191,11 +164,11 @@ public string GetEpiserverFieldName(FieldType fieldType) public int GetMetaFieldLength(FieldType fieldType) { - var defaultLength = 150; + int defaultLength = 150; if (fieldType.Settings.ContainsKey("MetaFieldLength")) { - if (!int.TryParse(fieldType.Settings["MetaFieldLength"], out defaultLength)) + if (!Int32.TryParse(fieldType.Settings["MetaFieldLength"], out defaultLength)) { return 150; } @@ -220,15 +193,15 @@ public string GetNameForEntity(Entity entity, int maxLength) nameField = GetField(entity, _config.EpiNameMapping[entity.EntityType.Id]); } - string returnString = string.Empty; + string returnString = String.Empty; if (nameField == null || nameField.IsEmpty()) { returnString = _pimFieldAdapter.GetDisplayName(entity, maxLength); } else if (nameField.FieldType.DataType.Equals(DataType.LocaleString)) { - var ls = (LocaleString) nameField.Data; - if (!string.IsNullOrEmpty(ls[_config.LanguageMapping[_config.ChannelDefaultLanguage]])) + var ls = (LocaleString)nameField.Data; + if (!String.IsNullOrEmpty(ls[_config.LanguageMapping[_config.ChannelDefaultLanguage]])) { returnString = ls[_config.LanguageMapping[_config.ChannelDefaultLanguage]]; } @@ -275,7 +248,7 @@ public bool IsChannelNodeLink(string linkTypeId) LinkType linkType = _config.LinkTypes.FirstOrDefault(x => x.Id == linkTypeId); return linkType?.SourceEntityTypeId == "ChannelNode" || - (linkType?.SourceEntityTypeId == "Channel" && linkType?.TargetEntityTypeId == "ChannelNode"); + (linkType?.SourceEntityTypeId == "Channel" && linkType.TargetEntityTypeId == "ChannelNode"); } /// @@ -294,6 +267,7 @@ public bool IsRelation(LinkType linkType) { return true; } + return linkType.SourceEntityTypeId.Equals("Product") && linkType.TargetEntityTypeId.Equals("Item") && linkType.Index == FirstProductItemLinkType; } @@ -311,10 +285,10 @@ public bool SkipField(FieldType fieldType) private Field GetField(Entity entity, string fieldTypeId) { - if (string.IsNullOrEmpty(fieldTypeId)) - return (Field) null; + if (String.IsNullOrEmpty(fieldTypeId)) + return null; return entity.Fields.FirstOrDefault(f => f.FieldType?.Id.ToLower() == fieldTypeId.ToLower()); } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/Helpers/IPimFieldAdapter.cs b/src/EpiserverAdapter/Helpers/IPimFieldAdapter.cs index be29920..ab61eb3 100644 --- a/src/EpiserverAdapter/Helpers/IPimFieldAdapter.cs +++ b/src/EpiserverAdapter/Helpers/IPimFieldAdapter.cs @@ -7,15 +7,15 @@ namespace Epinova.InRiverConnector.EpiserverAdapter.Helpers { public interface IPimFieldAdapter { - bool FieldTypeIsMultiLanguage(FieldType fieldType); - string GetAllowSearch(FieldType fieldType); IEnumerable CultureInfosToStringArray(CultureInfo[] cultureInfo); - string GetStartDate(Entity entity); - string GetEndDate(Entity entity); string FieldIsUseInCompare(FieldType fieldType); + bool FieldTypeIsMultiLanguage(FieldType fieldType); + string GetAllowSearch(FieldType fieldType); + List GetCVLValues(Field field); string GetDisplayName(Entity entity, int maxLength); + string GetEndDate(Entity entity); string GetFieldValue(Entity entity, string fieldName, CultureInfo ci); - List GetCVLValues(Field field); string GetFlatFieldData(Field field); + string GetStartDate(Entity entity); } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/Helpers/PimFieldAdapter.cs b/src/EpiserverAdapter/Helpers/PimFieldAdapter.cs index 9b26dc4..8b4ba0d 100644 --- a/src/EpiserverAdapter/Helpers/PimFieldAdapter.cs +++ b/src/EpiserverAdapter/Helpers/PimFieldAdapter.cs @@ -13,9 +13,9 @@ namespace Epinova.InRiverConnector.EpiserverAdapter.Helpers { public class PimFieldAdapter : IPimFieldAdapter { - private static List cvls; + private static List _cvls; - private static List cvlValues; + private static List _cvlValues; private readonly IConfiguration _config; public PimFieldAdapter(IConfiguration config) @@ -25,14 +25,14 @@ public PimFieldAdapter(IConfiguration config) public static List CVLs { - get => cvls ?? (cvls = RemoteManager.ModelService.GetAllCVLs()); - set => cvls = value; + get => _cvls ?? (_cvls = RemoteManager.ModelService.GetAllCVLs()); + set => _cvls = value; } public static List CVLValues { - get => cvlValues ?? (cvlValues = RemoteManager.ModelService.GetAllCVLValues()); - set => cvlValues = value; + get => _cvlValues ?? (_cvlValues = RemoteManager.ModelService.GetAllCVLValues()); + set => _cvlValues = value; } public IEnumerable CultureInfosToStringArray(CultureInfo[] cultureInfo) @@ -42,7 +42,7 @@ public IEnumerable CultureInfosToStringArray(CultureInfo[] cultureInfo) public string FieldIsUseInCompare(FieldType fieldType) { - var value = "False"; + string value = "False"; if (fieldType.Settings.ContainsKey("UseInComparing")) { @@ -120,10 +120,10 @@ public string GetDisplayName(Entity entity, int maxLength) } else if (displayNameField.FieldType.DataType.Equals(DataType.LocaleString)) { - var ls = (LocaleString) displayNameField.Data; - if (string.IsNullOrEmpty(ls[_config.LanguageMapping[_config.ChannelDefaultLanguage]])) + var ls = (LocaleString)displayNameField.Data; + if (String.IsNullOrEmpty(ls[_config.LanguageMapping[_config.ChannelDefaultLanguage]])) { - returnString = string.Format("[{0}]", entity.Id); + returnString = $"[{entity.Id}]"; } else { @@ -156,7 +156,7 @@ public string GetEndDate(Entity entity) return DateTime.UtcNow.AddYears(100).ToString("u"); } - return ((DateTime) endDateField.Data).ToUniversalTime().ToString("u"); + return ((DateTime)endDateField.Data).ToUniversalTime().ToString("u"); } public string GetFieldValue(Entity entity, string fieldName, CultureInfo ci) @@ -165,12 +165,12 @@ public string GetFieldValue(Entity entity, string fieldName, CultureInfo ci) if (field == null || field.IsEmpty()) { - return string.Empty; + return String.Empty; } if (field.FieldType.DataType.Equals(DataType.LocaleString)) { - return _config.ChannelIdPrefix + ((LocaleString) field.Data)[ci]; + return _config.ChannelIdPrefix + ((LocaleString)field.Data)[ci]; } return field.Data.ToString(); @@ -180,23 +180,23 @@ public string GetFlatFieldData(Field field) { if (field == null || field.IsEmpty()) { - return string.Empty; + return String.Empty; } string dataType = field.FieldType.DataType; if (dataType == DataType.Boolean) { - return ((bool) field.Data).ToString(); + return ((bool)field.Data).ToString(); } if (dataType == DataType.DateTime) { - return ((DateTime) field.Data).ToString("O"); + return ((DateTime)field.Data).ToString("O"); } if (dataType == DataType.Double) { - return ((double) field.Data).ToString(CultureInfo.InvariantCulture); + return ((double)field.Data).ToString(CultureInfo.InvariantCulture); } if (dataType == DataType.File || @@ -207,7 +207,7 @@ public string GetFlatFieldData(Field field) return field.Data.ToString(); } - return string.Empty; + return String.Empty; } public string GetStartDate(Entity entity) @@ -219,7 +219,7 @@ public string GetStartDate(Entity entity) return DateTime.UtcNow.AddMinutes(-5).ToString("u"); } - return ((DateTime) startDateField.Data).ToUniversalTime().ToString("u"); + return ((DateTime)startDateField.Data).ToUniversalTime().ToString("u"); } public string GetSingleCvlValue(string key, CultureInfo language, List currentCvlValues, CVL cvl) @@ -232,7 +232,7 @@ public string GetSingleCvlValue(string key, CultureInfo language, List if (cvl.DataType.Equals(DataType.LocaleString)) { - var ls = (LocaleString) cvlValue.Value; + var ls = (LocaleString)cvlValue.Value; if (!ls.ContainsCulture(language)) return null; @@ -261,20 +261,20 @@ internal static void CompareAndParseSkuXmls(string oldXml, string newXml, out Li foreach (XElement elem in oldSkus) { - XAttribute id = elem.Attribute("id"); - if (newSkus.Exists(e => e.Attribute("id").Value == id.Value)) + string idValue = elem.Attribute("id")?.Value; + if (newSkus.Exists(e => e.Attribute("id")?.Value == idValue)) { - if (!removables.Exists(y => y == id.Value)) + if (!removables.Exists(y => y == idValue)) { - removables.Add(id.Value); + removables.Add(idValue); } } } foreach (string id in removables) { - oldSkus.RemoveAll(e => e.Attribute("id").Value == id); - newSkus.RemoveAll(e => e.Attribute("id").Value == id); + oldSkus.RemoveAll(e => e.Attribute("id")?.Value == id); + newSkus.RemoveAll(e => e.Attribute("id")?.Value == id); } skusToAdd = newSkus; @@ -338,4 +338,4 @@ private string GetFinalizedValue(string value, string key) return value; } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/IConfiguration.cs b/src/EpiserverAdapter/IConfiguration.cs index d2e586f..8362f84 100644 --- a/src/EpiserverAdapter/IConfiguration.cs +++ b/src/EpiserverAdapter/IConfiguration.cs @@ -7,35 +7,35 @@ namespace Epinova.InRiverConnector.EpiserverAdapter { public interface IConfiguration { - int EpiRestTimeout { get; } + CVLDataMode ActiveCVLDataMode { get; } + LinkType[] AssociationLinkTypes { get; } + int BatchSize { get; } + string[] BundleEntityTypes { get; } + string ChannelDefaultCurrency { get; set; } + CultureInfo ChannelDefaultLanguage { get; set; } + string ChannelDefaultWeightBase { get; set; } + int ChannelId { get; } + string ChannelIdPrefix { get; set; } + string[] DynamicPackageEntityTypes { get; } + EndpointCollection Endpoints { get; set; } string EpiApiKey { get; } + Dictionary EpiCodeMapping { get; } string EpiEndpoint { get; } - EndpointCollection Endpoints { get; set; } - string Id { get; } - List LinkTypes { get; set; } - int ChannelId { get; } - string PublicationsRootPath { get; } + HashSet EPiFieldsIninRiver { get; } + Dictionary EpiNameMapping { get; } + int EpiRestTimeout { get; } List ExportEnabledEntityTypes { get; } bool ForceIncludeLinkedContent { get; } string HttpPostUrl { get; } + string Id { get; } + bool ItemsToSkus { get; } Dictionary LanguageMapping { get; } - Dictionary EpiNameMapping { get; } - string ResourcesRootPath { get; } - bool UseThreeLevelsInCommerce { get; } - CultureInfo ChannelDefaultLanguage { get; set; } - string ChannelDefaultCurrency { get; set; } - Dictionary EpiCodeMapping { get; } - string ChannelDefaultWeightBase { get; set; } - string ChannelIdPrefix { get; set; } + List LinkTypes { get; set; } + string[] PackageEntityTypes { get; } + string PublicationsRootPath { get; } string[] ResourceConfigurations { get; } Dictionary ResourceConfiugurationExtensions { get; } - LinkType[] AssociationLinkTypes { get; } - bool ItemsToSkus { get; } - int BatchSize { get; } - string[] BundleEntityTypes { get; } - string[] PackageEntityTypes { get; } - string[] DynamicPackageEntityTypes { get; } - HashSet EPiFieldsIninRiver { get; } - CVLDataMode ActiveCVLDataMode { get; } + string ResourcesRootPath { get; } + bool UseThreeLevelsInCommerce { get; } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/IEntityService.cs b/src/EpiserverAdapter/IEntityService.cs index 94ec404..87c9821 100644 --- a/src/EpiserverAdapter/IEntityService.cs +++ b/src/EpiserverAdapter/IEntityService.cs @@ -5,16 +5,16 @@ namespace Epinova.InRiverConnector.EpiserverAdapter { public interface IEntityService { - Entity GetEntity(int id, LoadLevel loadLevel); - List GetAllStructureEntitiesInChannel(List entityTypes); - List GetAllResourceLocations(int resourceEntityId); - List GetEntityInChannelWithParent(int channelId, int entityId, int parentId); - string GetTargetEntityPath(int targetEntityId, List channelEntities, int? parentId = null); - List GetChildrenEntitiesInChannel(int entityId, string path); - List GetStructureEntitiesForEntityInChannel(int channelId, int entityId); - StructureEntity GetParentStructureEntity(int channelId, int sourceEntityId, int targetEntityId, List channelEntities); void FlushCache(); + List GetAllResourceLocations(int resourceEntityId); + List GetAllStructureEntitiesInChannel(List entityTypes); List GetChannelNodeStructureEntitiesInPath(string path); + List GetChildrenEntitiesInChannel(int entityId, string path); + Entity GetEntity(int id, LoadLevel loadLevel); + List GetEntityInChannelWithParent(int channelId, int entityId, int parentId); Entity GetParentProduct(StructureEntity structureEntity); + StructureEntity GetParentStructureEntity(int channelId, int sourceEntityId, int targetEntityId, List channelEntities); + List GetStructureEntitiesForEntityInChannel(int channelId, int entityId); + string GetTargetEntityPath(int targetEntityId, List channelEntities, int? parentId = null); } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/Properties/AssemblyInfo.cs b/src/EpiserverAdapter/Properties/AssemblyInfo.cs index 6ccccfd..e7a0b9c 100644 --- a/src/EpiserverAdapter/Properties/AssemblyInfo.cs +++ b/src/EpiserverAdapter/Properties/AssemblyInfo.cs @@ -1,10 +1,6 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. [assembly: AssemblyTitle("Epinova.InRiverConnector.EpiserverAdapter")] [assembly: AssemblyDescription("")] [assembly: AssemblyCompany("")] @@ -12,19 +8,12 @@ [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("0e3285d3-f75a-454e-8583-9c6e35be565d")] - -[assembly: AssemblyVersion("1.3.0.0")] -[assembly: AssemblyFileVersion("1.3.0.0")] +[assembly: AssemblyVersion("1.4.0.0")] +[assembly: AssemblyFileVersion("1.4.0.0")] #if DEBUG [assembly: AssemblyConfiguration("Debug")] #else [assembly: AssemblyConfiguration("Release")] -#endif \ No newline at end of file +#endif diff --git a/src/EpiserverAdapter/ResourceImporter.cs b/src/EpiserverAdapter/ResourceImporter.cs index accbdd8..ae7165d 100644 --- a/src/EpiserverAdapter/ResourceImporter.cs +++ b/src/EpiserverAdapter/ResourceImporter.cs @@ -26,4 +26,4 @@ public async Task ImportResources(string resourceXmlFilePath, string baseResourc await _httpClient.PostWithAsyncStatusCheck(_config.Endpoints.ImportResources, importResourcesRequest); } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/SettingsValidator.cs b/src/EpiserverAdapter/SettingsValidator.cs index d541a32..e028ab3 100644 --- a/src/EpiserverAdapter/SettingsValidator.cs +++ b/src/EpiserverAdapter/SettingsValidator.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Configuration; namespace Epinova.InRiverConnector.EpiserverAdapter @@ -16,7 +17,7 @@ public void ValidateSettings() { if (SettingHasValue(ConfigKeys.ForceIncludeLinkedContent)) { - if(!bool.TryParse(_settings[ConfigKeys.ForceIncludeLinkedContent], out bool _)) + if (!Boolean.TryParse(_settings[ConfigKeys.ForceIncludeLinkedContent], out bool _)) throw new ConfigurationErrorsException($"Setting FORCE_INCLUDE_LINKED_CONTENT has invalid value. Set it to True or False. Default is {ConfigDefaults.ForceIncludeLinkedContent}"); } @@ -27,28 +28,25 @@ public void ValidateSettings() if (!SettingHasValue("EPI_ENDPOINT_URL")) { - throw new ConfigurationErrorsException("Missing EPI_ENDPOINT_URL setting on connector. It should point to the import end point on the EPiServer Commerce web site. Please see the documentation."); + throw new ConfigurationErrorsException( + "Missing EPI_ENDPOINT_URL setting on connector. It should point to the import end point on the EPiServer Commerce web site. Please see the documentation."); } ValidateEndpointAddress(_settings["EPI_ENDPOINT_URL"]); - var timeoutString = _settings["EPI_RESTTIMEOUT"]; - if (!SettingHasValue("EPI_RESTTIMEOUT") || !int.TryParse(timeoutString, out _)) + string timeoutString = _settings["EPI_RESTTIMEOUT"]; + if (!SettingHasValue("EPI_RESTTIMEOUT") || !Int32.TryParse(timeoutString, out _)) { throw new ConfigurationErrorsException("Missing or invalid EPI_RESTTIMEOUT. This should be a valid integer:" + timeoutString); } } - private bool SettingHasValue(string settingKey) - { - return _settings.ContainsKey(settingKey) && !string.IsNullOrWhiteSpace(_settings[settingKey]); - } - - private void ValidateEndpointAddress(string address) + private static void ValidateEndpointAddress(string address) { - if (string.IsNullOrEmpty(address)) + if (String.IsNullOrEmpty(address)) { - throw new ConfigurationErrorsException("Missing ImportEndPointAddress setting on connector. It should point to the import end point on the EPiServer Commerce web site. Please see the documentation."); + throw new ConfigurationErrorsException( + "Missing ImportEndPointAddress setting on connector. It should point to the import end point on the EPiServer Commerce web site. Please see the documentation."); } if (address.EndsWith("/") == false) @@ -56,5 +54,10 @@ private void ValidateEndpointAddress(string address) throw new ConfigurationErrorsException("Endpoint address should end with /"); } } + + private bool SettingHasValue(string settingKey) + { + return _settings.ContainsKey(settingKey) && !String.IsNullOrWhiteSpace(_settings[settingKey]); + } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/XmlFactories/CatalogDocumentFactory.cs b/src/EpiserverAdapter/XmlFactories/CatalogDocumentFactory.cs index 3877c75..a0ec647 100644 --- a/src/EpiserverAdapter/XmlFactories/CatalogDocumentFactory.cs +++ b/src/EpiserverAdapter/XmlFactories/CatalogDocumentFactory.cs @@ -1,6 +1,8 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Threading.Tasks; using System.Xml.Linq; using Epinova.InRiverConnector.EpiserverAdapter.Communication; using Epinova.InRiverConnector.EpiserverAdapter.Helpers; @@ -9,6 +11,8 @@ using inRiver.Remoting.Log; using inRiver.Remoting.Objects; +// ReSharper disable IdentifierTypo + namespace Epinova.InRiverConnector.EpiserverAdapter.XmlFactories { public class CatalogDocumentFactory @@ -93,7 +97,7 @@ public XDocument CreateUpdateDocument(Entity channelEntity, Entity updatedEntity if (updatedEntity.EntityType.Id == "ChannelNode") { - updatedNode = GetUpdatedNode(channelEntity, updatedEntity, updatedNode); + updatedNode = GetUpdatedNode(channelEntity, updatedEntity); } else if (shouldGetUpdatedEntry) { @@ -134,18 +138,18 @@ public XElement GetAssociationTypes() return new XElement("AssociationTypes", associationTypeElements); } - public CatalogElementContainer GetEPiElements(List structureEntities) + public async Task GetEPiElementsAsync(List structureEntities) { _epiElementContainer = new CatalogElementContainer(); - var totalLoaded = 0; + int totalLoaded = 0; int batchSize = _config.BatchSize; do { List batch = structureEntities.Skip(totalLoaded).Take(batchSize).ToList(); - AddNodeElements(batch); + await AddNodeElementsAsync(batch); AddEntryElements(batch); AddRelationElements(structureEntities); @@ -157,9 +161,12 @@ public CatalogElementContainer GetEPiElements(List structureEnt return _epiElementContainer; } - private void AddAssociationElements(LinkType linkType, - StructureEntity structureEntity, - string itemCode) + private static bool IsSpecificationLink(Link link) + { + return link.Target.EntityType.Id == "Specification"; + } + + private void AddAssociationElements(LinkType linkType, StructureEntity structureEntity, string itemCode) { IntegrationLogger.Write(LogLevel.Debug, "AddAssociationElements"); @@ -176,9 +183,7 @@ private void AddAssociationElements(LinkType linkType, } } - private void AddChannelNodeRelation(LinkType linkType, - StructureEntity structureEntity, - Entity entity) + private void AddChannelNodeRelation(LinkType linkType, StructureEntity structureEntity, Entity entity) { string addedRelationName = _catalogCodeGenerator.GetRelationName(entity.Id, structureEntity.ParentId); if (_epiElementContainer.HasRelation(addedRelationName)) @@ -192,9 +197,10 @@ private void AddChannelNodeRelation(LinkType linkType, $"Added Relation for Source {structureEntity.ParentId} and Target {structureEntity.EntityId} for LinkTypeId {linkType.Id}"); } - private void AddEntryElements(List batch) + private void AddEntryElements(IEnumerable batch) { - foreach (StructureEntity structureEntity in batch.Where(x => x.EntityId != _config.ChannelId && !x.IsChannelNode())) + foreach (StructureEntity structureEntity in batch + .Where(x => x.EntityId != _config.ChannelId && !x.IsChannelNode())) { Entity entity = _entityService.GetEntity(structureEntity.EntityId, LoadLevel.DataAndLinks); @@ -204,17 +210,16 @@ private void AddEntryElements(List batch) foreach (XElement sku in skus) { XElement codeElement = sku.Element("Code"); - if (codeElement != null && !_epiElementContainer.HasEntry(codeElement.Value)) - { - _epiElementContainer.AddEntry(sku, codeElement.Value); - IntegrationLogger.Write(LogLevel.Debug, $"Added Item/SKU {sku.Name.LocalName} to Entries"); - } + if (codeElement == null || _epiElementContainer.HasEntry(codeElement.Value)) + continue; + + _epiElementContainer.AddEntry(sku, codeElement.Value); + IntegrationLogger.Write(LogLevel.Debug, $"Added Item/SKU {sku.Name.LocalName} to Entries"); } } - if (structureEntity.IsItem() && _config.ItemsToSkus && _config.UseThreeLevelsInCommerce || - !ShouldCreateSkus(structureEntity)) + if ((!structureEntity.IsItem() || !_config.ItemsToSkus || !_config.UseThreeLevelsInCommerce) && ShouldCreateSkus(structureEntity)) continue; { if (structureEntity.IsItem() && !_channelHelper.ItemHasParentInChannel(structureEntity)) continue; @@ -240,9 +245,7 @@ private void AddEntryElements(List batch) } } - private void AddEntryRelationElement(StructureEntity structureEntity, - string skuCode, - LinkType linkType) + private void AddEntryRelationElement(StructureEntity structureEntity, string skuCode, LinkType linkType) { Entity parentProduct = _entityService.GetParentProduct(structureEntity); if (parentProduct == null) @@ -265,16 +268,14 @@ private void AddEntryRelationElement(StructureEntity structureEntity, IntegrationLogger.Write(LogLevel.Debug, $"Added EntryRelation for {skuCode} to product {parentCode}. Relation name: {addedRelationsName}."); } - private void AddItemToSkusAssociations(LinkType linkType, - StructureEntity structureEntity, - string skuId) + private void AddItemToSkusAssociations(LinkType linkType, StructureEntity structureEntity, string skuId) { string associationName = _epiMappingHelper.GetAssociationName(structureEntity); Entity source = _entityService.GetEntity(structureEntity.ParentId, LoadLevel.DataOnly); List skuCodes = _catalogElementFactory.SkuItemIds(source); - for (var i = 0; i < skuCodes.Count; i++) + for (int i = 0; i < skuCodes.Count; i++) { skuCodes[i] = _catalogCodeGenerator.GetPrefixedCode(skuCodes[i]); } @@ -288,7 +289,6 @@ private void AddItemToSkusAssociations(LinkType linkType, XElement existingCatalogAssociationElement = _epiElementContainer.Associations.FirstOrDefault( x => x.Element("Name")?.Value == associationName && x.Element("EntryCode")?.Value == skuCode); - ; var associationElement = new XElement("Association", new XElement("EntryCode", skuId), @@ -340,7 +340,7 @@ private void AddMissingParentRelation(StructureEntity structureEntity, string sk AddEntryRelationElement(structureEntity, skuId, new LinkType()); } - private void AddNodeElements(List batch) + private async Task AddNodeElementsAsync(IEnumerable batch) { IEnumerable nodeStructureEntities = batch.Where(x => x.IsChannelNode() && x.EntityId != _config.ChannelId); @@ -350,7 +350,14 @@ private void AddNodeElements(List batch) if (_config.ChannelId == structureEntity.ParentId) { - _epiApi.MoveNodeToRootIfNeeded(entity.Id); + try + { + await _epiApi.MoveNodeToRootIfNeededAsync(entity.Id); + } + catch (Exception ex) + { + IntegrationLogger.Write(LogLevel.Warning, $"Could not process entity {entity.Id}. Message: {ex.Message}"); + } } IntegrationLogger.Write(LogLevel.Debug, $"Trying to add channelNode {entity.Id} to Nodes"); @@ -379,7 +386,7 @@ private void AddNodeElements(List batch) { string oldSortOrder = sortOrderElement.Value; sortOrderElement.Value = linkIndex.ToString(CultureInfo.InvariantCulture); - linkIndex = int.Parse(oldSortOrder); + linkIndex = Int32.Parse(oldSortOrder); } } @@ -438,11 +445,11 @@ private void AddNormalAssociations(StructureEntity structureEntity) { XElement newElement = _catalogElementFactory.CreateAssociationElement(structureEntity); - if (!existingAssociation.Descendants().Any(e => e.Name.LocalName == "EntryCode" && e.Value == entityCode)) - { - existingAssociation.Add(newElement); - _epiElementContainer.AddAssociationKey(associationKey); - } + if (existingAssociation.Descendants().Any(e => e.Name.LocalName == "EntryCode" && e.Value == entityCode)) + return; + + existingAssociation.Add(newElement); + _epiElementContainer.AddAssociationKey(associationKey); } else { @@ -451,7 +458,7 @@ private void AddNormalAssociations(StructureEntity structureEntity) } } - private void AddRelationElements(List allChannelStructureEntities) + private void AddRelationElements(IEnumerable allChannelStructureEntities) { foreach (StructureEntity structureEntity in allChannelStructureEntities.Where(x => x.EntityId != _config.ChannelId && x.Type != "Resource")) { @@ -471,9 +478,7 @@ private void AddRelationElements(List allChannelStructureEntiti } } - private void AddRelations(LinkType linkType, - StructureEntity structureEntity, - Entity entity) + private void AddRelations(LinkType linkType, StructureEntity structureEntity, Entity entity) { var skus = new List { _catalogCodeGenerator.GetEpiserverCode(entity.Id) }; @@ -482,7 +487,7 @@ private void AddRelations(LinkType linkType, if (structureEntity.IsItem() && _config.ItemsToSkus) { skus = _catalogElementFactory.SkuItemIds(entity); - for (var i = 0; i < skus.Count; i++) + for (int i = 0; i < skus.Count; i++) { skus[i] = _catalogCodeGenerator.GetPrefixedCode(skus[i]); } @@ -557,10 +562,10 @@ private XElement GetSpecificationMetaField(Entity entity) return specificationMetaField; } - private XElement GetUpdatedNode(Entity channelEntity, Entity updatedEntity, XElement updatedNode) + private XElement GetUpdatedNode(Entity channelEntity, Entity updatedEntity) { Link nodeLink = updatedEntity.Links.Find(l => l.Source.Id == channelEntity.Id); - var sortOrder = 0; + int sortOrder = 0; if (nodeLink != null) { sortOrder = nodeLink.Index; @@ -574,14 +579,9 @@ private bool IsAssociationLinkType(LinkType linkType) return _config.AssociationLinkTypes.Any(x => x.Id == linkType.Id); } - private bool IsSpecificationLink(Link link) - { - return link.Target.EntityType.Id == "Specification"; - } - private bool ShouldCreateSkus(StructureEntity structureEntity) { return structureEntity.IsItem() && _config.ItemsToSkus; } } -} \ No newline at end of file +} diff --git a/src/EpiserverAdapter/XmlFactories/CatalogElementFactory.cs b/src/EpiserverAdapter/XmlFactories/CatalogElementFactory.cs index 37386aa..3d2931d 100644 --- a/src/EpiserverAdapter/XmlFactories/CatalogElementFactory.cs +++ b/src/EpiserverAdapter/XmlFactories/CatalogElementFactory.cs @@ -8,14 +8,15 @@ using inRiver.Remoting; using inRiver.Remoting.Log; using inRiver.Remoting.Objects; +// ReSharper disable IdentifierTypo namespace Epinova.InRiverConnector.EpiserverAdapter.XmlFactories { public class CatalogElementFactory { + private readonly CatalogCodeGenerator _catalogCodeGenerator; private readonly IConfiguration _config; private readonly EpiMappingHelper _mappingHelper; - private readonly CatalogCodeGenerator _catalogCodeGenerator; private readonly IPimFieldAdapter _pimFieldAdapter; public CatalogElementFactory(IConfiguration config, EpiMappingHelper mappingHelper, CatalogCodeGenerator catalogCodeGenerator, IPimFieldAdapter pimFieldAdapter) @@ -26,109 +27,120 @@ public CatalogElementFactory(IConfiguration config, EpiMappingHelper mappingHelp _pimFieldAdapter = pimFieldAdapter; } - public XElement InRiverEntityTypeToMetaClass(string name, string entityTypeName) + public XElement CreateAssociationElement(StructureEntity structureEntity) { return new XElement( - "MetaClass", - new XElement("Namespace", "Mediachase.Commerce.Catalog.User"), + "Association", + new XElement("EntryCode", _catalogCodeGenerator.GetEpiserverCode(structureEntity.EntityId)), + new XElement("SortOrder", structureEntity.SortOrder), + new XElement("Type", structureEntity.LinkTypeIdFromParent)); + } + + public XElement CreateAssociationTypeElement(LinkType linkType) + { + return new XElement( + "AssociationType", + new XElement("TypeId", linkType.Id), + new XElement("Description", linkType.Id)); + } + + public XElement CreateCatalogAssociationElement(StructureEntity structureEntity, Dictionary channelEntities = null) + { + string name = _mappingHelper.GetAssociationName(structureEntity); + + return new XElement( + "CatalogAssociation", new XElement("Name", name), - new XElement("FriendlyName", name), - new XElement("MetaClassType", "User"), - new XElement("ParentClass", _mappingHelper.GetParentClassForEntityType(entityTypeName)), - new XElement("TableName", _mappingHelper.GetTableNameForEntityType(entityTypeName, name)), - new XElement("Description", "From inRiver"), - new XElement("IsSystem", "False"), - new XElement("IsAbstract", "False"), - new XElement("FieldListChangedSqlScript"), - new XElement("Tag"), - new XElement("Attributes")); + new XElement("Description", structureEntity.LinkTypeIdFromParent), + new XElement("SortOrder", structureEntity.SortOrder), + new XElement("EntryCode", _catalogCodeGenerator.GetEpiserverCode(structureEntity.ParentId)), + CreateAssociationElement(structureEntity)); } - public XElement InRiverFieldTypeToMetaField(FieldType fieldType) + public XElement CreateCatalogElement(Entity channel) + { + return new XElement("Catalog", + new XAttribute("name", _mappingHelper.GetNameForEntity(channel, 100)), + new XAttribute(@"lastmodified", channel.LastModified.ToString("O")), + new XAttribute("startDate", _pimFieldAdapter.GetStartDate(channel)), + new XAttribute("endDate", _pimFieldAdapter.GetEndDate(channel)), + new XAttribute("defaultCurrency", _config.ChannelDefaultCurrency), + new XAttribute("weightBase", _config.ChannelDefaultWeightBase), + new XAttribute("defaultLanguage", _config.ChannelDefaultLanguage.Name.ToLower()), + new XAttribute("sortOrder", 0), + new XAttribute("isActive", "True"), + new XAttribute("languages", String.Join(",", _pimFieldAdapter.CultureInfosToStringArray(_config.LanguageMapping.Keys.ToArray())))); + } + + public XElement CreateEntryRelationElement(string parentCode, string parentEntityType, string childCode, int sortOrder) { + string relationType = "ProductVariation"; + + if (String.IsNullOrEmpty(parentEntityType)) + return new XElement( + "EntryRelation", + new XElement("ParentEntryCode", parentCode), + new XElement("ChildEntryCode", childCode), + new XElement("RelationType", relationType), + new XElement("Quantity", 0), + new XElement("GroupName", "default"), + new XElement("SortOrder", sortOrder)); + string sourceType = _mappingHelper.GetEntryType(parentEntityType); + + if (sourceType == "Package" || sourceType == "DynamicPackage") + relationType = "PackageEntry"; + else if (sourceType == "Bundle") + relationType = "BundleEntry"; + return new XElement( - "MetaField", - new XElement("Namespace", "Mediachase.Commerce.Catalog"), - new XElement("Name", _mappingHelper.GetEpiserverFieldName(fieldType)), - new XElement("FriendlyName", _mappingHelper.GetEpiserverFieldName(fieldType)), - new XElement("Description", "From inRiver"), - new XElement("DataType", _mappingHelper.GetEpiserverDataType(fieldType)), - new XElement("Length", _mappingHelper.GetMetaFieldLength(fieldType)), - new XElement("AllowNulls", !fieldType.Mandatory), - new XElement("SaveHistory", "False"), - new XElement("AllowSearch", _pimFieldAdapter.GetAllowSearch(fieldType)), - new XElement("MultiLanguageValue", _pimFieldAdapter.FieldTypeIsMultiLanguage(fieldType)), - new XElement("IsSystem", "False"), - new XElement("Tag"), - new XElement("Attributes", - new XElement("Attribute", - new XElement("Key", "useincomparing"), - new XElement("Value", _pimFieldAdapter.FieldIsUseInCompare(fieldType)))), - new XElement("OwnerMetaClass", fieldType.EntityTypeId)); + "EntryRelation", + new XElement("ParentEntryCode", parentCode), + new XElement("ChildEntryCode", childCode), + new XElement("RelationType", relationType), + new XElement("Quantity", 0), + new XElement("GroupName", "default"), + new XElement("SortOrder", sortOrder)); } - public XElement CreateEpiserverLongStringField(string name) + public XElement CreateEpiserverLongHtmlField(string name) { return new XElement( "MetaField", - new XElement("Namespace", "Mediachase.Commerce.Catalog"), + new XElement("Namespace", @"Mediachase.Commerce.Catalog"), new XElement("Name", name), new XElement("FriendlyName", name), new XElement("Description", "From inRiver"), - new XElement("DataType", "LongString"), - new XElement("Length", 150), + new XElement("DataType", "LongHtmlString"), + new XElement("Length", 65000), new XElement("AllowNulls", "True"), new XElement("SaveHistory", "False"), new XElement("AllowSearch", "True"), new XElement("MultiLanguageValue", "True"), new XElement("IsSystem", "False"), new XElement("Tag"), - new XElement("Attributes", - new XElement("Attribute", new XElement("Key", "useincomparing"), new XElement("Value", "True")))); + new XElement( + "Attributes", + new XElement("Attribute", new XElement("Key", @"useincomparing"), new XElement("Value", "False")))); } - public XElement CreateEpiserverLongHtmlField(string name) + public XElement CreateEpiserverLongStringField(string name) { return new XElement( "MetaField", - new XElement("Namespace", "Mediachase.Commerce.Catalog"), + new XElement("Namespace", @"Mediachase.Commerce.Catalog"), new XElement("Name", name), new XElement("FriendlyName", name), new XElement("Description", "From inRiver"), - new XElement("DataType", "LongHtmlString"), - new XElement("Length", 65000), + new XElement("DataType", "LongString"), + new XElement("Length", 150), new XElement("AllowNulls", "True"), new XElement("SaveHistory", "False"), new XElement("AllowSearch", "True"), new XElement("MultiLanguageValue", "True"), new XElement("IsSystem", "False"), new XElement("Tag"), - new XElement( - "Attributes", - new XElement("Attribute", new XElement("Key", "useincomparing"), new XElement("Value", "False")))); - } - - public XElement CreateAssociationTypeElement(LinkType linkType) - { - return new XElement( - "AssociationType", - new XElement("TypeId", linkType.Id), - new XElement("Description", linkType.Id)); - } - - public XElement CreateCatalogElement(Entity channel) - { - return new XElement("Catalog", - new XAttribute("name", _mappingHelper.GetNameForEntity(channel, 100)), - new XAttribute("lastmodified", channel.LastModified.ToString("O")), - new XAttribute("startDate", _pimFieldAdapter.GetStartDate(channel)), - new XAttribute("endDate", _pimFieldAdapter.GetEndDate(channel)), - new XAttribute("defaultCurrency", _config.ChannelDefaultCurrency), - new XAttribute("weightBase", _config.ChannelDefaultWeightBase), - new XAttribute("defaultLanguage", _config.ChannelDefaultLanguage.Name.ToLower()), - new XAttribute("sortOrder", 0), - new XAttribute("isActive", "True"), - new XAttribute("languages", string.Join(",", _pimFieldAdapter.CultureInfosToStringArray(_config.LanguageMapping.Keys.ToArray())))); + new XElement("Attributes", + new XElement("Attribute", new XElement("Key", @"useincomparing"), new XElement("Value", "True")))); } public XElement CreateNodeElement(Entity entity, int parentId, int sortOrder) @@ -139,7 +151,7 @@ public XElement CreateNodeElement(Entity entity, int parentId, int sortOrder) new XElement("EndDate", _pimFieldAdapter.GetEndDate(entity)), new XElement("IsActive", true.ToString()), new XElement("SortOrder", sortOrder), - new XElement("DisplayTemplate", string.Empty), + new XElement("DisplayTemplate", String.Empty), new XElement("Guid", GetChannelEntityGuid(_config.ChannelId, entity.Id)), new XElement("Code", _catalogCodeGenerator.GetEpiserverCode(entity)), new XElement("MetaData", @@ -151,118 +163,81 @@ from f in entity.Fields where !f.IsEmpty() && !_mappingHelper.SkipField(f.FieldType) select GetMetaFieldValueElement(f))), new XElement("ParentNode", _catalogCodeGenerator.GetEpiserverCode(parentId)), - CreateSEOInfoElement(entity)); + CreateSeoInfoElement(entity)); } - public XElement CreateSEOInfoElement(Entity entity) + public XElement CreateNodeEntryRelation(int sourceId, int targetId, int sortOrder) { - var seoInfo = new XElement("SeoInfo"); - foreach (var culturePair in _config.LanguageMapping) - { - var uri = _pimFieldAdapter.GetFieldValue(entity, "seouri", culturePair.Value); - var title = _pimFieldAdapter.GetFieldValue(entity, "seotitle", culturePair.Value); - var description = _pimFieldAdapter.GetFieldValue(entity, "seodescription", culturePair.Value); - var keywords = _pimFieldAdapter.GetFieldValue(entity, "seokeywords", culturePair.Value); - var urisegment = _pimFieldAdapter.GetFieldValue(entity, "seourisegment", culturePair.Value); - - if (string.IsNullOrEmpty(uri) && - string.IsNullOrEmpty(title) && - string.IsNullOrEmpty(description) && - string.IsNullOrEmpty(keywords) && - string.IsNullOrEmpty(urisegment)) - continue; - - seoInfo.Add( - new XElement("Seo", - new XElement("LanguageCode", culturePair.Key.Name.ToLower()), - string.IsNullOrEmpty(uri) ? null : new XElement("Uri", uri), - string.IsNullOrEmpty(title) ? null : new XElement("Title", title), - string.IsNullOrEmpty(description) ? null : new XElement("Description", description), - string.IsNullOrEmpty(keywords) ? null : new XElement("Keywords", keywords), - string.IsNullOrEmpty(urisegment) ? null : new XElement("UriSegment", urisegment))); - } - return seoInfo; + return new XElement("NodeEntryRelation", + new XElement("EntryCode", _catalogCodeGenerator.GetEpiserverCode(targetId)), + new XElement("NodeCode", _catalogCodeGenerator.GetEpiserverCode(sourceId)), + new XElement("SortOrder", sortOrder)); } - public XElement InRiverEntityToEpiEntry(Entity entity) + public XElement CreateNodeEntryRelation(string nodeCode, string skuId, int sortOrder) { - var metaFields = from f in entity.Fields - where UseField(entity, f) && !_mappingHelper.SkipField(f.FieldType) - select GetMetaFieldValueElement(f); - - return new XElement("Entry", - new XElement("Name", _mappingHelper.GetNameForEntity(entity, 100)), - new XElement("StartDate", _pimFieldAdapter.GetStartDate(entity)), - new XElement("EndDate", _pimFieldAdapter.GetEndDate(entity)), - new XElement("IsActive", "True"), - new XElement("DisplayTemplate", string.Empty), - new XElement("Code", _catalogCodeGenerator.GetEpiserverCode(entity)), - new XElement("EntryType", _mappingHelper.GetEntryType(entity.EntityType.Id)), - new XElement("Guid", GetChannelEntityGuid(_config.ChannelId, entity.Id)), - new XElement( - "MetaData", - new XElement("MetaClass", new XElement("Name", GetMetaClassForEntity(entity))), - new XElement( - "MetaFields", - GetDisplayFieldElement(entity.DisplayName, "DisplayName"), - GetDisplayFieldElement(entity.DisplayDescription, "DisplayDescription"), - metaFields)), - CreateSEOInfoElement(entity) - ); + return new XElement("NodeEntryRelation", + new XElement("EntryCode", skuId), + new XElement("NodeCode", nodeCode), + new XElement("SortOrder", sortOrder)); } - private Guid GetChannelEntityGuid(int channelId, int entityId) + public XElement CreateNodeRelation(int sourceId, int targetId, int sortOrder) { - var concatIds = channelId.ToString().PadLeft(16, '0') + entityId.ToString().PadLeft(16, '0'); - return new Guid(concatIds); + return new XElement("NodeRelation", + new XElement("ChildNodeCode", _catalogCodeGenerator.GetEpiserverCode(targetId)), + new XElement("ParentNodeCode", _catalogCodeGenerator.GetEpiserverCode(sourceId)), + new XElement("SortOrder", sortOrder)); } - public XElement GetMetaFieldValueElement(Field field) + + public XElement CreateResourceMetaFieldsElement(EntityType resourceType) { - XElement metaField = new XElement( - "MetaField", - new XElement("Name", _mappingHelper.GetEpiserverFieldName(field.FieldType)), - new XElement("Type", _mappingHelper.GetEpiserverDataType(field.FieldType)) - ); + return new XElement( + "ResourceMetaFields", + resourceType.FieldTypes.Select( + fieldtype => + new XElement( + "ResourceMetaField", + new XElement("FieldName", _mappingHelper.GetEpiserverFieldName(fieldtype)), + new XElement("FriendlyName", _mappingHelper.GetEpiserverFieldName(fieldtype)), + new XElement("Description", _mappingHelper.GetEpiserverFieldName(fieldtype)), + new XElement("FieldType", _mappingHelper.GetEpiserverDataType(fieldtype)), + new XElement("Format", "Text"), + new XElement("MaximumLength", _mappingHelper.GetMetaFieldLength(fieldtype)), + new XElement("AllowNulls", !fieldtype.Mandatory), + new XElement("UniqueValue", fieldtype.Unique)))); + } - if (field.FieldType.DataType.Equals(DataType.LocaleString)) - { - var ls = field.Data as LocaleString; - if (!field.IsEmpty()) - { - foreach (var culturePair in _config.LanguageMapping) - { - if (ls != null) - { - metaField.Add( - new XElement("Data", - new XAttribute("language", culturePair.Key.Name.ToLower()), - new XAttribute("value", ls[culturePair.Value] ?? string.Empty))); - } - } - } - else - { - foreach (var culturePair in _config.LanguageMapping) - { - metaField.Add(new XElement("Data", new XAttribute("language", culturePair.Key.Name.ToLower()), new XAttribute("value", string.Empty))); - } - } - } - else if (field.FieldType.DataType.Equals(DataType.CVL)) - { - var cvlDataElement = _pimFieldAdapter.GetCVLValues(field); - metaField.Add(cvlDataElement); - } - else + public XElement CreateSeoInfoElement(Entity entity) + { + var seoInfo = new XElement("SeoInfo"); + foreach (KeyValuePair culturePair in _config.LanguageMapping) { - metaField.Add( - new XElement("Data", - new XAttribute("language", _config.ChannelDefaultLanguage.Name.ToLower()), - new XAttribute("value", _pimFieldAdapter.GetFlatFieldData(field)))); + string uri = _pimFieldAdapter.GetFieldValue(entity, @"seouri", culturePair.Value); + string title = _pimFieldAdapter.GetFieldValue(entity, @"seotitle", culturePair.Value); + string description = _pimFieldAdapter.GetFieldValue(entity, @"seodescription", culturePair.Value); + string keywords = _pimFieldAdapter.GetFieldValue(entity, @"seokeywords", culturePair.Value); + string uriSegment = _pimFieldAdapter.GetFieldValue(entity, @"seourisegment", culturePair.Value); + + if (String.IsNullOrEmpty(uri) && + String.IsNullOrEmpty(title) && + String.IsNullOrEmpty(description) && + String.IsNullOrEmpty(keywords) && + String.IsNullOrEmpty(uriSegment)) + continue; + + seoInfo.Add( + new XElement("Seo", + new XElement("LanguageCode", culturePair.Key.Name.ToLower()), + String.IsNullOrEmpty(uri) ? null : new XElement("Uri", uri), + String.IsNullOrEmpty(title) ? null : new XElement("Title", title), + String.IsNullOrEmpty(description) ? null : new XElement("Description", description), + String.IsNullOrEmpty(keywords) ? null : new XElement("Keywords", keywords), + String.IsNullOrEmpty(uriSegment) ? null : new XElement("UriSegment", uriSegment))); } - return metaField; + return seoInfo; } public XElement CreateSimpleMetaFieldElement(string name, string value) @@ -276,104 +251,102 @@ public XElement CreateSimpleMetaFieldElement(string name, string value) new XAttribute("value", value))); } - public XElement CreateNodeRelation(int sourceId, int targetId, int sortOrder) + public List GenerateSkuItemElemetsFromItem(Entity item) { - return new XElement("NodeRelation", - new XElement("ChildNodeCode", _catalogCodeGenerator.GetEpiserverCode(targetId)), - new XElement("ParentNodeCode", _catalogCodeGenerator.GetEpiserverCode(sourceId)), - new XElement("SortOrder", sortOrder)); - } + XDocument skuDoc = SkuFieldToDocument(item); + if (skuDoc.Root == null || skuDoc.Element("SKUs") == null) + { + return new List(); + } - public XElement CreateNodeEntryRelation(int sourceId, int targetId, int sortOrder) - { - return new XElement("NodeEntryRelation", - new XElement("EntryCode", _catalogCodeGenerator.GetEpiserverCode(targetId)), - new XElement("NodeCode", _catalogCodeGenerator.GetEpiserverCode(sourceId)), - new XElement("SortOrder", sortOrder)); - } + Link specLink = item.OutboundLinks.Find(l => l.Target.EntityType.Id == "Specification"); + XElement specificationMetaField = null; + if (specLink != null) + { + specificationMetaField = new XElement("MetaField", + new XElement("Name", "SpecificationField"), + new XElement("Type", "LongHtmlString")); - public XElement CreateNodeEntryRelation(string nodeCode, string skuId, int sortOrder) - { - return new XElement("NodeEntryRelation", - new XElement("EntryCode", skuId), - new XElement("NodeCode", nodeCode), - new XElement("SortOrder", sortOrder)); - } + foreach (KeyValuePair culturePair in _config.LanguageMapping) + { + string htmlData = RemoteManager.DataService.GetSpecificationAsHtml(specLink.Target.Id, item.Id, culturePair.Value); + specificationMetaField.Add( + new XElement("Data", + new XAttribute("language", culturePair.Key.Name.ToLower()), + new XAttribute("value", htmlData))); + } + } - public XElement CreateEntryRelationElement(string parentCode, string parentEntityType, string childCode, int sortOrder) - { - string relationType = "ProductVariation"; + var skuElements = new List(); + XElement skuElement = skuDoc.Element("SKUs"); + if (skuElement == null) + return skuElements; + + foreach (XElement sku in skuElement.Elements()) + { + string skuId = sku.Attribute("id")?.Value; + if (String.IsNullOrEmpty(skuId)) + { + IntegrationLogger.Write(LogLevel.Information, $"Could not find the id for the SKU data for item: {item.Id}"); + continue; + } + + XElement itemElement = InRiverEntityToEpiEntry(item); + XElement nameElement = sku.Element("Name"); + if (nameElement != null) + { + string name = (!String.IsNullOrEmpty(nameElement.Value)) ? nameElement.Value : skuId; + XElement itemElementName = itemElement.Element("Name"); + if (itemElementName != null) + { + itemElementName.Value = name; + } + } - if (!string.IsNullOrEmpty(parentEntityType)) - { - var sourceType = _mappingHelper.GetEntryType(parentEntityType); - switch (sourceType) + XElement codeElement = itemElement.Element("Code"); + if (codeElement != null) { - case "Package": - case "DynamicPackage": - relationType = "PackageEntry"; - break; - case "Bundle": - relationType = "BundleEntry"; - break; + codeElement.Value = _catalogCodeGenerator.GetPrefixedCode(skuId); } - } - - return new XElement( - "EntryRelation", - new XElement("ParentEntryCode", parentCode), - new XElement("ChildEntryCode", childCode), - new XElement("RelationType", relationType), - new XElement("Quantity", 0), - new XElement("GroupName", "default"), - new XElement("SortOrder", sortOrder)); - } - public XElement CreateCatalogAssociationElement(StructureEntity structureEntity, Dictionary channelEntities = null) - { - string name = _mappingHelper.GetAssociationName(structureEntity); + XElement entryTypeElement = itemElement.Element("EntryType"); + if (entryTypeElement != null) + { + entryTypeElement.Value = "Variation"; + } - return new XElement( - "CatalogAssociation", - new XElement("Name", name), - new XElement("Description", structureEntity.LinkTypeIdFromParent), - new XElement("SortOrder", structureEntity.SortOrder), - new XElement("EntryCode", _catalogCodeGenerator.GetEpiserverCode(structureEntity.ParentId)), - CreateAssociationElement(structureEntity)); - } + XElement skuDataElement = sku.Element(FieldNames.SKUData); + if (skuDataElement != null) + { + foreach (XElement skuData in skuDataElement.Elements()) + { + XElement metaDataElement = itemElement.Element("MetaData"); + if (metaDataElement?.Element("MetaFields") != null) + { + metaDataElement.Element("MetaFields")?.Add(CreateSimpleMetaFieldElement(skuData.Name.LocalName, skuData.Value)); + } + } + } - public XElement CreateAssociationElement(StructureEntity structureEntity) - { - return new XElement( - "Association", - new XElement("EntryCode", _catalogCodeGenerator.GetEpiserverCode(structureEntity.EntityId)), - new XElement("SortOrder", structureEntity.SortOrder), - new XElement("Type", structureEntity.LinkTypeIdFromParent)); - } + if (specificationMetaField != null) + { + XElement metaDataElement = itemElement.Element("MetaData"); + if (metaDataElement?.Element("MetaFields") != null) + { + metaDataElement.Element("MetaFields")?.Add(specificationMetaField); + } + } + skuElements.Add(itemElement); + } - public XElement CreateResourceMetaFieldsElement(EntityType resourceType) - { - return new XElement( - "ResourceMetaFields", - resourceType.FieldTypes.Select( - fieldtype => - new XElement( - "ResourceMetaField", - new XElement("FieldName", _mappingHelper.GetEpiserverFieldName(fieldtype)), - new XElement("FriendlyName", _mappingHelper.GetEpiserverFieldName(fieldtype)), - new XElement("Description", _mappingHelper.GetEpiserverFieldName(fieldtype)), - new XElement("FieldType", _mappingHelper.GetEpiserverDataType(fieldtype)), - new XElement("Format", "Text"), - new XElement("MaximumLength", _mappingHelper.GetMetaFieldLength(fieldtype)), - new XElement("AllowNulls", !fieldtype.Mandatory), - new XElement("UniqueValue", fieldtype.Unique)))); + return skuElements; } public XElement GetMetaClassesFromFieldSets() { - List metaClasses = new List(); - List metafields = new List(); + var metaClasses = new List(); + var metafields = new List(); XElement diaplyNameElement = CreateEpiserverLongStringField("DisplayName"); XElement displayDescriptionElement = CreateEpiserverLongStringField("DisplayDescription"); @@ -385,16 +358,17 @@ public XElement GetMetaClassesFromFieldSets() if (entityType.LinkTypes.Find(a => a.TargetEntityTypeId == "Specification") != null && entityType.Id != "Specification") { specification.Add(new XElement("OwnerMetaClass", entityType.Id)); - foreach (FieldSet fieldSet in entityType.FieldSets) + + foreach (string name in entityType.FieldSets + .Select(fieldSet => entityType.Id + "_" + fieldSet.Id)) { - string name = entityType.Id + "_" + fieldSet.Id; specification.Add(new XElement("OwnerMetaClass", name)); } addSpec = true; } - Dictionary> fieldTypesFieldSets = new Dictionary>(); + var fieldTypesFieldSets = new Dictionary>(); metaClasses.Add(InRiverEntityTypeToMetaClass(entityType.Id, entityType.Id)); foreach (FieldSet fieldset in entityType.FieldSets) { @@ -436,9 +410,9 @@ public XElement GetMetaClassesFromFieldSets() } else { - foreach (FieldSet fieldSet in entityType.FieldSets) + foreach (string name in entityType.FieldSets + .Select(fieldSet => entityType.Id + "_" + fieldSet.Id)) { - string name = entityType.Id + "_" + fieldSet.Id; metaField.Add(new XElement("OwnerMetaClass", name)); } } @@ -454,11 +428,11 @@ public XElement GetMetaClassesFromFieldSets() XElement nameElement = mf.Element("Name"); return nameElement != null && nameElement.Value.Equals(_mappingHelper.GetEpiserverFieldName(fieldType)); }); - if (existingMetaField != null) - { - var movefields = metaField.Elements("OwnerMetaClass"); - existingMetaField.Add(movefields); - } + + if (existingMetaField == null) continue; + + IEnumerable movefields = metaField.Elements("OwnerMetaClass"); + existingMetaField.Add(movefields); } else { @@ -477,102 +451,124 @@ public XElement GetMetaClassesFromFieldSets() return new XElement("MetaDataPlusBackup", new XAttribute("version", "1.0"), metaClasses.ToArray(), metafields.ToArray()); } - public List GenerateSkuItemElemetsFromItem(Entity item) + public XElement GetMetaFieldValueElement(Field field) { - XDocument skuDoc = SkuFieldToDocument(item); - if (skuDoc.Root == null || skuDoc.Element("SKUs") == null) - { - return new List(); - } - - Link specLink = item.OutboundLinks.Find(l => l.Target.EntityType.Id == "Specification"); - XElement specificationMetaField = null; - if (specLink != null) - { - specificationMetaField = new XElement("MetaField", - new XElement("Name", "SpecificationField"), - new XElement("Type", "LongHtmlString")); - - foreach (KeyValuePair culturePair in _config.LanguageMapping) - { - string htmlData = RemoteManager.DataService.GetSpecificationAsHtml(specLink.Target.Id, item.Id, culturePair.Value); - specificationMetaField.Add( - new XElement("Data", - new XAttribute("language", culturePair.Key.Name.ToLower()), - new XAttribute("value", htmlData))); - } - } - - List skuElements = new List(); - XElement skuElement = skuDoc.Element("SKUs"); - if (skuElement == null) - return skuElements; + var metaField = new XElement( + "MetaField", + new XElement("Name", _mappingHelper.GetEpiserverFieldName(field.FieldType)), + new XElement("Type", _mappingHelper.GetEpiserverDataType(field.FieldType)) + ); - foreach (XElement sku in skuElement.Elements()) + if (field.FieldType.DataType.Equals(DataType.LocaleString)) { - string skuId = sku.Attribute("id").Value; - if (string.IsNullOrEmpty(skuId)) - { - IntegrationLogger.Write(LogLevel.Information, $"Could not find the id for the SKU data for item: {item.Id}"); - continue; - } - - XElement itemElement = InRiverEntityToEpiEntry(item); - XElement nameElement = sku.Element("Name"); - if (nameElement != null) + var ls = field.Data as LocaleString; + if (!field.IsEmpty()) { - string name = (!string.IsNullOrEmpty(nameElement.Value)) ? nameElement.Value : skuId; - XElement itemElementName = itemElement.Element("Name"); - if (itemElementName != null) + foreach (KeyValuePair culturePair in _config.LanguageMapping + .Where(culturePair => ls != null)) { - itemElementName.Value = name; + metaField.Add( + new XElement("Data", + new XAttribute("language", culturePair.Key.Name.ToLower()), + new XAttribute("value", ls?[culturePair.Value] ?? String.Empty))); } } - - XElement codeElement = itemElement.Element("Code"); - if (codeElement != null) - { - codeElement.Value = _catalogCodeGenerator.GetPrefixedCode(skuId); - } - - XElement entryTypeElement = itemElement.Element("EntryType"); - if (entryTypeElement != null) - { - entryTypeElement.Value = "Variation"; - } - - XElement skuDataElement = sku.Element(FieldNames.SKUData); - if (skuDataElement != null) + else { - foreach (XElement skuData in skuDataElement.Elements()) + foreach (KeyValuePair culturePair in _config.LanguageMapping) { - XElement metaDataElement = itemElement.Element("MetaData"); - if (metaDataElement?.Element("MetaFields") != null) - { - metaDataElement.Element("MetaFields")?.Add(CreateSimpleMetaFieldElement(skuData.Name.LocalName, skuData.Value)); - } + metaField.Add(new XElement("Data", new XAttribute("language", culturePair.Key.Name.ToLower()), new XAttribute("value", String.Empty))); } } + } + else if (field.FieldType.DataType.Equals(DataType.CVL)) + { + List cvlDataElement = _pimFieldAdapter.GetCVLValues(field); + metaField.Add(cvlDataElement); + } + else + { + metaField.Add( + new XElement("Data", + new XAttribute("language", _config.ChannelDefaultLanguage.Name.ToLower()), + new XAttribute("value", _pimFieldAdapter.GetFlatFieldData(field)))); + } - if (specificationMetaField != null) - { - XElement metaDataElement = itemElement.Element("MetaData"); - if (metaDataElement?.Element("MetaFields") != null) - { - metaDataElement.Element("MetaFields")?.Add(specificationMetaField); - } - } + return metaField; + } - skuElements.Add(itemElement); - } + public XElement InRiverEntityToEpiEntry(Entity entity) + { + IEnumerable metaFields = from f in entity.Fields + where UseField(entity, f) && !_mappingHelper.SkipField(f.FieldType) + select GetMetaFieldValueElement(f); - return skuElements; + return new XElement("Entry", + new XElement("Name", _mappingHelper.GetNameForEntity(entity, 100)), + new XElement("StartDate", _pimFieldAdapter.GetStartDate(entity)), + new XElement("EndDate", _pimFieldAdapter.GetEndDate(entity)), + new XElement("IsActive", "True"), + new XElement("DisplayTemplate", String.Empty), + new XElement("Code", _catalogCodeGenerator.GetEpiserverCode(entity)), + new XElement("EntryType", _mappingHelper.GetEntryType(entity.EntityType.Id)), + new XElement("Guid", GetChannelEntityGuid(_config.ChannelId, entity.Id)), + new XElement( + "MetaData", + new XElement("MetaClass", new XElement("Name", GetMetaClassForEntity(entity))), + new XElement( + "MetaFields", + GetDisplayFieldElement(entity.DisplayName, "DisplayName"), + GetDisplayFieldElement(entity.DisplayDescription, "DisplayDescription"), + metaFields)), + CreateSeoInfoElement(entity) + ); + } + + public XElement InRiverEntityTypeToMetaClass(string name, string entityTypeName) + { + return new XElement( + "MetaClass", + new XElement("Namespace", @"Mediachase.Commerce.Catalog.User"), + new XElement("Name", name), + new XElement("FriendlyName", name), + new XElement("MetaClassType", "User"), + new XElement("ParentClass", _mappingHelper.GetParentClassForEntityType(entityTypeName)), + new XElement("TableName", _mappingHelper.GetTableNameForEntityType(entityTypeName, name)), + new XElement("Description", "From inRiver"), + new XElement("IsSystem", "False"), + new XElement("IsAbstract", "False"), + new XElement("FieldListChangedSqlScript"), + new XElement("Tag"), + new XElement("Attributes")); + } + + public XElement InRiverFieldTypeToMetaField(FieldType fieldType) + { + return new XElement( + "MetaField", + new XElement("Namespace", @"Mediachase.Commerce.Catalog"), + new XElement("Name", _mappingHelper.GetEpiserverFieldName(fieldType)), + new XElement("FriendlyName", _mappingHelper.GetEpiserverFieldName(fieldType)), + new XElement("Description", "From inRiver"), + new XElement("DataType", _mappingHelper.GetEpiserverDataType(fieldType)), + new XElement("Length", _mappingHelper.GetMetaFieldLength(fieldType)), + new XElement("AllowNulls", !fieldType.Mandatory), + new XElement("SaveHistory", "False"), + new XElement("AllowSearch", _pimFieldAdapter.GetAllowSearch(fieldType)), + new XElement("MultiLanguageValue", _pimFieldAdapter.FieldTypeIsMultiLanguage(fieldType)), + new XElement("IsSystem", "False"), + new XElement("Tag"), + new XElement("Attributes", + new XElement("Attribute", + new XElement("Key", @"useincomparing"), + new XElement("Value", _pimFieldAdapter.FieldIsUseInCompare(fieldType)))), + new XElement("OwnerMetaClass", fieldType.EntityTypeId)); } public XDocument SkuFieldToDocument(Entity item) { Field skuField = item.GetField(FieldNames.SKUFieldName); - if (skuField == null || skuField.Data == null) + if (skuField?.Data == null) { XElement itemElement = InRiverEntityToEpiEntry(item); IntegrationLogger.Write(LogLevel.Information, $"Could not find SKU data for item: {item.Id}"); @@ -595,15 +591,22 @@ public List SkuItemIds(Entity item) XElement skusElement = skuDoc.Element("SKUs"); if (skusElement != null) { - return - (from skuElement in skusElement.Elements() - where skuElement.HasAttributes - select skuElement.Attribute("id").Value).ToList(); + return skusElement.Elements() + .Where(skuElement => skuElement.HasAttributes) + .Select(skuElement => skuElement.Attribute("id")?.Value) + .Where(id => id != null) + .ToList(); } return new List(); } + private static Guid GetChannelEntityGuid(int channelId, int entityId) + { + string concatIds = channelId.ToString().PadLeft(16, '0') + entityId.ToString().PadLeft(16, '0'); + return new Guid(concatIds); + } + private XElement GetDisplayFieldElement(Field displayField, string name) { if (displayField == null || displayField.IsEmpty()) @@ -613,11 +616,11 @@ private XElement GetDisplayFieldElement(Field displayField, string name) new XElement("Type", "LongHtmlString"), new XElement("Data", new XAttribute("language", _config.ChannelDefaultLanguage.Name.ToLower()), - new XAttribute("value", string.Empty))); + new XAttribute("value", String.Empty))); } - var element = GetMetaFieldValueElement(displayField); - var nameElement = element.Element("Name"); + XElement element = GetMetaFieldValueElement(displayField); + XElement nameElement = element.Element("Name"); if (nameElement != null) { nameElement.Value = name; @@ -632,47 +635,39 @@ private XElement GetDisplayFieldElement(Field displayField, string name) return element; } - private bool UseField(Entity entity, Field field) + private static string GetMetaClassForEntity(Entity entity) + { + if (!String.IsNullOrEmpty(entity.FieldSetId) && entity.EntityType.FieldSets.Any(fs => fs.Id == entity.FieldSetId)) + return entity.EntityType.Id + "_" + entity.FieldSetId; + + return entity.EntityType.Id; + } + + private static bool UseField(Entity entity, Field field) { if (!field.FieldType.ExcludeFromDefaultView) - { return true; - } + + List
otherFieldSets = entity.EntityType.FieldSets + .Where(fs => !fs.Id.Equals(entity.FieldSetId)).ToList(); - List
otherFieldSets = entity.EntityType.FieldSets.Where(fs => !fs.Id.Equals(entity.FieldSetId)).ToList(); if (otherFieldSets.Count == 0) - { return true; - } - - FieldSet fieldSet = entity.EntityType.FieldSets.Find(fs => fs.Id.Equals(entity.FieldSetId)); - if (fieldSet != null) - { - if (fieldSet.FieldTypes.Contains(field.FieldType.Id)) - { - return true; - } - } - - foreach (FieldSet fs in otherFieldSets) - { - if (fs.FieldTypes.Contains(field.FieldType.Id)) - { - return false; - } - } - - return true; - } - - private string GetMetaClassForEntity(Entity entity) - { - if (!string.IsNullOrEmpty(entity.FieldSetId) && entity.EntityType.FieldSets.Any(fs => fs.Id == entity.FieldSetId)) - { - return entity.EntityType.Id + "_" + entity.FieldSetId; - } - - return entity.EntityType.Id; + + FieldSet fieldSet = entity.EntityType.FieldSets + .Find(fs => fs.Id.Equals(entity.FieldSetId)); + + if (fieldSet == null) + return otherFieldSets + .All(fs => !fs.FieldTypes + .Contains(field.FieldType.Id)); + + if (fieldSet.FieldTypes.Contains(field.FieldType.Id)) + return true; + + return otherFieldSets + .All(fs => !fs.FieldTypes + .Contains(field.FieldType.Id)); } } } diff --git a/src/EpiserverAdapter/XmlFactories/ResourceElementFactory.cs b/src/EpiserverAdapter/XmlFactories/ResourceElementFactory.cs index 85a73a3..d5d69e8 100644 --- a/src/EpiserverAdapter/XmlFactories/ResourceElementFactory.cs +++ b/src/EpiserverAdapter/XmlFactories/ResourceElementFactory.cs @@ -14,19 +14,19 @@ namespace Epinova.InRiverConnector.EpiserverAdapter.XmlFactories { public class ResourceElementFactory { - private readonly CatalogElementFactory _catalogElementFactory; - private readonly EpiMappingHelper _mappingHelper; private readonly CatalogCodeGenerator _catalogCodeGenerator; + private readonly CatalogElementFactory _catalogElementFactory; private readonly IConfiguration _config; private readonly IEntityService _entityService; + private readonly EpiMappingHelper _mappingHelper; private Dictionary _isImageCache; - - public ResourceElementFactory(CatalogElementFactory catalogElementFactory, - EpiMappingHelper mappingHelper, - CatalogCodeGenerator catalogCodeGenerator, - IConfiguration config, - IEntityService entityService) + + public ResourceElementFactory(CatalogElementFactory catalogElementFactory, + EpiMappingHelper mappingHelper, + CatalogCodeGenerator catalogCodeGenerator, + IConfiguration config, + IEntityService entityService) { _catalogElementFactory = catalogElementFactory; _mappingHelper = mappingHelper; @@ -41,10 +41,10 @@ public XElement CreateResourceElement(Entity resource, string action) { IntegrationLogger.Write(LogLevel.Debug, $"Creating resource element for resource ID {resource.Id} resource entities found."); - Dictionary parents = new Dictionary(); - - var allResourceLocations = _entityService.GetAllResourceLocations(resource.Id); - + var parents = new Dictionary(); + + List allResourceLocations = _entityService.GetAllResourceLocations(resource.Id); + var links = new List(); foreach (Link inboundLink in resource.InboundLinks) @@ -58,25 +58,25 @@ public XElement CreateResourceElement(Entity resource, string action) foreach (Link link in links) { Entity linkedEntity = link.Source; - + var ids = new List { _catalogCodeGenerator.GetEpiserverCode(linkedEntity) }; if (_config.UseThreeLevelsInCommerce) { ids.Add(_catalogCodeGenerator.GetEpiserverCode(linkedEntity)); - }; + } if (_config.ItemsToSkus && linkedEntity.EntityType.Id == "Item") { List skuIds = _catalogElementFactory.SkuItemIds(linkedEntity); foreach (string skuId in skuIds) { - var prefixedSkuId = _catalogCodeGenerator.GetPrefixedCode(skuId); + string prefixedSkuId = _catalogCodeGenerator.GetPrefixedCode(skuId); ids.Add(prefixedSkuId); } } - foreach (var id in ids) + foreach (string id in ids) { if (!parents.ContainsKey(id)) { @@ -85,37 +85,37 @@ public XElement CreateResourceElement(Entity resource, string action) } } - var resourceId = _catalogCodeGenerator.GetEpiserverCode(resource); + string resourceId = _catalogCodeGenerator.GetEpiserverCode(resource); string resourceFileId = null; - var resourceFileIdField = resource.GetField(FieldNames.ResourceFileId); + Field resourceFileIdField = resource.GetField(FieldNames.ResourceFileId); if (resourceFileIdField != null && !resourceFileIdField.IsEmpty()) { resourceFileId = resource.GetField(FieldNames.ResourceFileId).Data.ToString(); } - var metaFields = resource.Fields.Where(field => !_mappingHelper.SkipField(field.FieldType)) - .Select(field => _catalogElementFactory.GetMetaFieldValueElement(field)); + IEnumerable metaFields = resource.Fields.Where(field => !_mappingHelper.SkipField(field.FieldType)) + .Select(field => _catalogElementFactory.GetMetaFieldValueElement(field)); - var parentEntries = parents.Select(parent => new XElement("EntryCode", parent.Key, - new XAttribute("IsMainPicture", IsMainPicture(parent, resourceFileId)))); + IEnumerable parentEntries = parents.Select(parent => new XElement("EntryCode", parent.Key, + new XAttribute("IsMainPicture", IsMainPicture(parent, resourceFileId)))); return new XElement("Resource", - new XAttribute("id", resourceId), - new XAttribute("action", action), - new XElement("ResourceFields", metaFields), - GetInternalPaths(resource), - new XElement("ParentEntries", parentEntries)); + new XAttribute("id", resourceId), + new XAttribute("action", action), + new XElement("ResourceFields", metaFields), + GetInternalPaths(resource), + new XElement("ParentEntries", parentEntries)); } - private static bool IsMainPicture(KeyValuePair parent, string resourceFileId) + public void FlushCache() { - return parent.Value != null && parent.Value.ToString().Equals(resourceFileId); + _isImageCache = new Dictionary(); } public XDocument GetResourcesNodeForChannelEntities(List channelEntities, string resourcesBasePath) { - XDocument resourceDocument = new XDocument(); + var resourceDocument = new XDocument(); try { if (!Directory.Exists(_config.ResourcesRootPath)) @@ -123,7 +123,7 @@ public XDocument GetResourcesNodeForChannelEntities(List channe Directory.CreateDirectory(_config.ResourcesRootPath); } - List resourceIds = new List(); + var resourceIds = new List(); foreach (StructureEntity structureEntity in channelEntities) { if (structureEntity.Type == "Resource" && !resourceIds.Contains(structureEntity.EntityId)) @@ -138,7 +138,7 @@ public XDocument GetResourcesNodeForChannelEntities(List channe SaveFileToDisk(res, resourcesBasePath); } - resourceDocument = CreateResourceDocument(resources, resources, ImporterActions.Added, true); + resourceDocument = CreateResourceDocument(resources, ImporterActions.Added, true); } catch (Exception ex) { @@ -147,29 +147,48 @@ public XDocument GetResourcesNodeForChannelEntities(List channe return resourceDocument; } - - internal XDocument HandleResourceUpdate(Entity updatedResource, string folderDateTime) - { - SaveFileToDisk(updatedResource, folderDateTime); - List channelResources = new List(); - channelResources.Add(updatedResource); - - return CreateResourceDocument(channelResources, new List { updatedResource }, ImporterActions.Updated, false); - } - internal XDocument CreateResourceDocument(List channelResources, List resources, string action, bool addMetadata) + internal XDocument CreateResourceDocument(List resources, string action, bool addMetadata) { XElement resourceMetaClasses = null; if (addMetadata) { - var reourceType = resources.Count > 0 ? resources[0].EntityType : RemoteManager.ModelService.GetEntityType("Resource"); + EntityType reourceType = resources.Count > 0 ? resources[0].EntityType : RemoteManager.ModelService.GetEntityType("Resource"); resourceMetaClasses = _catalogElementFactory.CreateResourceMetaFieldsElement(reourceType); } - return new XDocument(new XElement("Resources", - resourceMetaClasses, - new XElement("ResourceFiles", - resources.Select(res => CreateResourceElement(res, action))))); + return new XDocument(new XElement("Resources", + resourceMetaClasses, + new XElement("ResourceFiles", + resources.Select(res => CreateResourceElement(res, action))))); + } + + internal XElement GetInternalPaths(Entity resource) + { + int id = GetResourceFileId(resource); + + var paths = new XElement("Paths"); + + if (id < 0) + { + return paths; + } + + foreach (string displayConfiguration in GetDisplayConfigurations(resource)) + { + string fileName = GetResourceFileName(resource, id, displayConfiguration); + string folder = GetFolderName(displayConfiguration, resource); + paths.Add(new XElement("Path", $"./{folder}/{fileName}")); + } + + return paths; + } + + internal XDocument HandleResourceUpdate(Entity updatedResource, string folderDateTime) + { + string folder = Path.Combine(_config.ResourcesRootPath, folderDateTime); + SaveFileToDisk(updatedResource, folder); + return CreateResourceDocument(new List { updatedResource }, ImporterActions.Updated, false); } internal bool SaveFileToDisk(Entity resource, string resourcesBasePath) @@ -192,17 +211,17 @@ internal bool SaveFileToDisk(Entity resource, string resourcesBasePath) return false; } - var fileName = GetResourceFileName(resource, resourceFileId, displayConfiguration); + string fileName = GetResourceFileName(resource, resourceFileId, displayConfiguration); - var folder = GetFolderName(displayConfiguration, resource); - var dir = Path.Combine(resourcesBasePath, folder); + string folder = GetFolderName(displayConfiguration, resource); + string dir = Path.Combine(resourcesBasePath, folder); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } - var fullFilePath = Path.Combine(dir, fileName); + string fullFilePath = Path.Combine(dir, fileName); File.WriteAllBytes(fullFilePath, resourceData); IntegrationLogger.Write(LogLevel.Debug, $"Saving Resource {resource.Id} to {fullFilePath}."); @@ -221,25 +240,36 @@ internal bool SaveFileToDisk(Entity resource, string resourcesBasePath) return true; } - internal XElement GetInternalPaths(Entity resource) + private static bool IsMainPicture(KeyValuePair parent, string resourceFileId) { - int id = GetResourceFileId(resource); + return parent.Value != null && parent.Value.ToString().Equals(resourceFileId); + } + + private IEnumerable GetDisplayConfigurations(Entity resource) + { + if (IsImage(resource)) + { + return _config.ResourceConfigurations; + } - XElement paths = new XElement("Paths"); + IntegrationLogger.Write(LogLevel.Debug, $"No image configuration found for Resource {resource.Id}. Original will be used"); + return new[] { Configuration.OriginalDisplayConfiguration }; + } - if (id < 0) + private string GetFolderName(string displayConfiguration, Entity resource) + { + if (!String.IsNullOrEmpty(displayConfiguration) && IsImage(resource)) { - return paths; + return displayConfiguration; } - foreach (string displayConfiguration in GetDisplayConfigurations(resource)) + Field mimeTypeField = resource.GetField(FieldNames.ResourceMimeType); + if (mimeTypeField != null && !mimeTypeField.IsEmpty() && mimeTypeField.Data.ToString().Contains('/')) { - string fileName = GetResourceFileName(resource, id, displayConfiguration); - string folder = GetFolderName(displayConfiguration, resource); - paths.Add(new XElement("Path", string.Format("./{0}/{1}", folder, fileName))); + return mimeTypeField.Data.ToString().Split('/')[1]; } - return paths; + return displayConfiguration; } private int GetResourceFileId(Entity resource) @@ -262,15 +292,15 @@ private string GetResourceFileName(Entity resource, int resourceFileId, string d string fileType = Path.GetExtension(resourceFileNameField.Data.ToString()); if (displayConfiguration != Configuration.OriginalDisplayConfiguration) { - string extension = string.Empty; + string extension = String.Empty; if (_config.ResourceConfiugurationExtensions.ContainsKey(displayConfiguration)) { extension = _config.ResourceConfiugurationExtensions[displayConfiguration]; } - - if (string.IsNullOrEmpty(extension)) + + if (String.IsNullOrEmpty(extension)) { - fileType = ".jpg"; + fileType = ".jpg"; } else { @@ -285,53 +315,21 @@ private string GetResourceFileName(Entity resource, int resourceFileId, string d return fileName; } - private IEnumerable GetDisplayConfigurations(Entity resource) - { - if (IsImage(resource)) - { - return _config.ResourceConfigurations; - } - - IntegrationLogger.Write(LogLevel.Debug, $"No image configuration found for Resource {resource.Id}. Original will be used"); - return new[] { Configuration.OriginalDisplayConfiguration }; - } - private bool IsImage(Entity resource) { - var fileEnding = resource.GetField("ResourceFilename")?.Data?.ToString().Split('.').LastOrDefault(); + string fileEnding = resource.GetField("ResourceFilename")?.Data?.ToString().Split('.').LastOrDefault(); - if (string.IsNullOrWhiteSpace(fileEnding)) + if (String.IsNullOrWhiteSpace(fileEnding)) return false; if (_isImageCache.ContainsKey(fileEnding)) return _isImageCache[fileEnding]; - var imageServiceConfigs = RemoteManager.UtilityService.GetAllImageServiceConfigurations(); - var configsHasExtension = imageServiceConfigs.Any(x => x.Extension.Equals(fileEnding, StringComparison.InvariantCultureIgnoreCase)); + List imageServiceConfigs = RemoteManager.UtilityService.GetAllImageServiceConfigurations(); + bool configsHasExtension = imageServiceConfigs.Any(x => x.Extension.Equals(fileEnding, StringComparison.InvariantCultureIgnoreCase)); _isImageCache.Add(fileEnding, configsHasExtension); return configsHasExtension; } - - public void FlushCache() - { - _isImageCache = new Dictionary(); - } - - private string GetFolderName(string displayConfiguration, Entity resource) - { - if (!string.IsNullOrEmpty(displayConfiguration) && IsImage(resource)) - { - return displayConfiguration; - } - - Field mimeTypeField = resource.GetField(FieldNames.ResourceMimeType); - if (mimeTypeField != null && !mimeTypeField.IsEmpty() && mimeTypeField.Data.ToString().Contains('/')) - { - return mimeTypeField.Data.ToString().Split('/')[1]; - } - - return displayConfiguration; - } } } diff --git a/src/EpiserverAdapter/packages.config b/src/EpiserverAdapter/packages.config index 7ee8c10..019e27e 100644 --- a/src/EpiserverAdapter/packages.config +++ b/src/EpiserverAdapter/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/src/EpiserverImporter/CatalogImporter.cs b/src/EpiserverImporter/CatalogImporter.cs index 58bf247..dbcbd0b 100644 --- a/src/EpiserverImporter/CatalogImporter.cs +++ b/src/EpiserverImporter/CatalogImporter.cs @@ -9,6 +9,7 @@ using EPiServer; using EPiServer.Commerce.Catalog.ContentTypes; using EPiServer.Commerce.Catalog.Linking; +using EPiServer.Core; using EPiServer.Logging; using EPiServer.Security; using EPiServer.ServiceLocation; @@ -16,27 +17,26 @@ using Mediachase.Commerce.Catalog.Dto; using Mediachase.Commerce.Catalog.ImportExport; using Mediachase.Commerce.Catalog.Managers; -using Mediachase.Commerce.Catalog.Objects; namespace Epinova.InRiverConnector.EpiserverImporter { public class CatalogImporter : ICatalogImporter { + private readonly IAssociationRepository _associationRepository; + private readonly ICatalogService _catalogService; + private readonly Configuration _config; + private readonly IContentRepository _contentRepository; private readonly ILogger _logger; private readonly ReferenceConverter _referenceConverter; - private readonly IContentRepository _contentRepository; - private readonly Configuration _config; private readonly IRelationRepository _relationRepository; - private readonly ICatalogService _catalogService; - private readonly IAssociationRepository _associationRepository; - public CatalogImporter(ILogger logger, - ReferenceConverter referenceConverter, - IContentRepository contentRepository, - Configuration config, - IRelationRepository relationRepository, - ICatalogService catalogService, - IAssociationRepository associationRepository) + public CatalogImporter(ILogger logger, + ReferenceConverter referenceConverter, + IContentRepository contentRepository, + Configuration config, + IRelationRepository relationRepository, + ICatalogService catalogService, + IAssociationRepository associationRepository) { _logger = logger; _referenceConverter = referenceConverter; @@ -47,12 +47,49 @@ public CatalogImporter(ILogger logger, _associationRepository = associationRepository; } - + public void DeleteAssociation(string sourceCode, string targetCode) + { + _logger.Debug($"Deleting association between {sourceCode} and {targetCode}."); + ContentReference sourceReference = _referenceConverter.GetContentLink(sourceCode); + ContentReference targetReference = _referenceConverter.GetContentLink(targetCode); + + IEnumerable associations = _associationRepository.GetAssociations(sourceReference); + Association existingAssociation = associations.FirstOrDefault(x => x.Target.Equals(targetReference)); + if (existingAssociation != null) + { + _associationRepository.RemoveAssociation(existingAssociation); + } + } + + public void DeleteCatalog(int catalogId) + { + List importerHandlers = ServiceLocator.Current.GetAllInstances().ToList(); + + if (_config.RunDeleteActionsHandlers) + { + foreach (IDeleteActionsHandler handler in importerHandlers) + { + handler.PreDeleteCatalog(catalogId); + } + } + + CatalogContext.Current.DeleteCatalog(catalogId); + + if (_config.RunDeleteActionsHandlers) + { + foreach (IDeleteActionsHandler handler in importerHandlers) + { + handler.PostDeleteCatalog(catalogId); + } + } + } + + public void DeleteCatalogEntry(string code) { List deleteHandlers = ServiceLocator.Current.GetAllInstances().ToList(); - var contentReference = _referenceConverter.GetContentLink(code); + ContentReference contentReference = _referenceConverter.GetContentLink(code); var entry = _contentRepository.Get(contentReference); if (entry == null) @@ -60,18 +97,19 @@ public void DeleteCatalogEntry(string code) _logger.Warning($"Could not find catalog entry with id: {code}. No entry is deleted"); return; } + if (_config.RunDeleteActionsHandlers) { - foreach (var handler in deleteHandlers) + foreach (IDeleteActionsHandler handler in deleteHandlers) { handler.PreDeleteCatalogEntry(entry); } } - var relatedChildren = _catalogService.GetChildren(entry); - foreach (var child in relatedChildren) + IEnumerable relatedChildren = _catalogService.GetChildren(entry); + foreach (EntryContentBase child in relatedChildren) { - var entryRelations = _catalogService.GetParents(child); + IEnumerable entryRelations = _catalogService.GetParents(child); if (entryRelations.Count() > 1) continue; @@ -84,39 +122,16 @@ public void DeleteCatalogEntry(string code) if (_config.RunDeleteActionsHandlers) { - foreach (var handler in deleteHandlers) + foreach (IDeleteActionsHandler handler in deleteHandlers) { handler.PostDeleteCatalogEntry(entry); } } } - public void DeleteCatalog(int catalogId) - { - List importerHandlers = ServiceLocator.Current.GetAllInstances().ToList(); - - if (_config.RunDeleteActionsHandlers) - { - foreach (IDeleteActionsHandler handler in importerHandlers) - { - handler.PreDeleteCatalog(catalogId); - } - } - - CatalogContext.Current.DeleteCatalog(catalogId); - - if (_config.RunDeleteActionsHandlers) - { - foreach (IDeleteActionsHandler handler in importerHandlers) - { - handler.PostDeleteCatalog(catalogId); - } - } - } - public void DeleteCatalogNode(string code) { - var contentReference = _referenceConverter.GetContentLink(code, CatalogContentType.CatalogNode); + ContentReference contentReference = _referenceConverter.GetContentLink(code, CatalogContentType.CatalogNode); if (!_contentRepository.TryGet(contentReference, out NodeContent nodeToDelete)) { _logger.Error($"DeleteCatalogNode called with a code that doesn't exist or is not a catalog node: {code}"); @@ -133,13 +148,13 @@ public void DeleteCatalogNode(string code) } } - var children = _contentRepository.GetChildren(nodeToDelete.ContentLink); + IEnumerable children = _contentRepository.GetChildren(nodeToDelete.ContentLink); - foreach (var child in children.Where(ShouldDeleteChild)) + foreach (EntryContentBase child in children.Where(ShouldDeleteChild)) { _contentRepository.Delete(child.ContentLink, true, AccessLevel.NoAccess); } - + _contentRepository.Delete(nodeToDelete.ContentLink, true, AccessLevel.NoAccess); if (_config.RunDeleteActionsHandlers) @@ -151,21 +166,33 @@ public void DeleteCatalogNode(string code) } } - public bool ShouldDeleteChild(EntryContentBase child) + public bool DeleteCompleted(DeleteCompletedData data) { - var nodeRelations = _relationRepository.GetParents(child.ContentLink); - return nodeRelations.Count() == 1; + if (_config.RunInRiverEventsHandlers) + { + IEnumerable eventsHandlers = ServiceLocator.Current.GetAllInstances(); + foreach (IInRiverEventsHandler handler in eventsHandlers) + { + handler.DeleteCompleted(data.CatalogName, data.EventType); + } + + _logger.Debug("*** DeleteCompleted events with parameters CatalogName={data.CatalogName}, EventType={data.EventType}"); + } + + return true; } - public void MoveNodeToRootIfNeeded(string catalogNodeId) + public void DeleteRelation(string sourceCode, string targetCode) { - CatalogNodeDto nodeDto = CatalogContext.Current.GetCatalogNodeDto(catalogNodeId); - if (nodeDto.CatalogNode.Count > 0) + _logger.Debug($"Deleting relation between {sourceCode} and {targetCode}."); + ContentReference sourceReference = _referenceConverter.GetContentLink(sourceCode); + ContentReference targetReference = _referenceConverter.GetContentLink(targetCode); + + IEnumerable entryRelations = _relationRepository.GetChildren(sourceReference); + Relation relation = entryRelations.FirstOrDefault(x => x.Child.Equals(targetReference)); + if (relation != null) { - if (nodeDto.CatalogNode[0].ParentNodeId != 0) - { - MoveNode(nodeDto.CatalogNode[0].Code, 0); - } + _relationRepository.RemoveRelation(relation); } } @@ -181,7 +208,7 @@ public void ImportCatalogXml(string path) _logger.Information($"Importing catalog document from {path}"); - var catalogImportHandlers = ServiceLocator.Current.GetAllInstances().ToList(); + List catalogImportHandlers = ServiceLocator.Current.GetAllInstances().ToList(); if (catalogImportHandlers.Any() && _config.RunCatalogImportHandlers) { _logger.Information("Importing with pre- and post-import handlers."); @@ -203,11 +230,10 @@ public void ImportCatalogXml(string path) _logger.Information("Successfully imported Catalog.xml."); ImportStatusContainer.Instance.IsImporting = false; - ImportStatusContainer.Instance.Message = "Import Sucessful"; + ImportStatusContainer.Instance.Message = "Import Successful"; }); } - public bool ImportUpdateCompleted(ImportUpdateCompletedData data) { if (_config.RunInRiverEventsHandlers) @@ -224,48 +250,22 @@ public bool ImportUpdateCompleted(ImportUpdateCompletedData data) return true; } - public bool DeleteCompleted(DeleteCompletedData data) + public void MoveNodeToRootIfNeeded(string catalogNodeId) { - if (_config.RunInRiverEventsHandlers) + CatalogNodeDto nodeDto = CatalogContext.Current.GetCatalogNodeDto(catalogNodeId); + if (nodeDto.CatalogNode.Count > 0) { - IEnumerable eventsHandlers = ServiceLocator.Current.GetAllInstances(); - foreach (IInRiverEventsHandler handler in eventsHandlers) + if (nodeDto.CatalogNode[0].ParentNodeId != 0) { - handler.DeleteCompleted(data.CatalogName, data.EventType); + MoveNode(nodeDto.CatalogNode[0].Code, 0); } - - _logger.Debug("*** DeleteCompleted events with parameters CatalogName={data.CatalogName}, EventType={data.EventType}"); - } - - return true; - } - - public void DeleteAssociation(string sourceCode, string targetCode) - { - _logger.Debug($"Deleting association between {sourceCode} and {targetCode}."); - var sourceReference = _referenceConverter.GetContentLink(sourceCode); - var targetReference = _referenceConverter.GetContentLink(targetCode); - - var associations = _associationRepository.GetAssociations(sourceReference); - var existingAssociation = associations.FirstOrDefault(x => x.Target.Equals(targetReference)); - if (existingAssociation != null) - { - _associationRepository.RemoveAssociation(existingAssociation); } } - public void DeleteRelation(string sourceCode, string targetCode) + public bool ShouldDeleteChild(EntryContentBase child) { - _logger.Debug($"Deleting relation between {sourceCode} and {targetCode}."); - var sourceReference = _referenceConverter.GetContentLink(sourceCode); - var targetReference = _referenceConverter.GetContentLink(targetCode); - - var entryRelations = _relationRepository.GetChildren(sourceReference); - var relation = entryRelations.FirstOrDefault(x => x.Child.Equals(targetReference)); - if (relation != null) - { - _relationRepository.RemoveRelation(relation); - } + IEnumerable nodeRelations = _relationRepository.GetParents(child.ContentLink); + return nodeRelations.Count() == 1; } private void ImportCatalog(string path) @@ -273,7 +273,7 @@ private void ImportCatalog(string path) var cie = new CatalogImportExport(); cie.ImportExportProgressMessage += ProgressHandler; - var directoryName = Path.GetDirectoryName(path); + string directoryName = Path.GetDirectoryName(path); cie.Import(directoryName, true); } @@ -283,8 +283,8 @@ private void ImportCatalogWithHandlers(string filePath, List public IEnumerable GetChildren(EntryContentBase entry) { - var relations = _relationRepository.GetChildren(entry.ContentLink); - var variations = relations.Select(x => _contentLoader.Get(x.Child)); + IEnumerable relations = _relationRepository.GetChildren(entry.ContentLink); + IEnumerable variations = relations.Select(x => _contentLoader.Get(x.Child)); return variations.Where(x => x != null); } @@ -39,4 +39,4 @@ public IEnumerable GetParents(EntryContentBase entry) return _relationRepository.GetParents(entry.ContentLink); } } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/Configuration.cs b/src/EpiserverImporter/Configuration.cs index 1a1daa6..9c58854 100644 --- a/src/EpiserverImporter/Configuration.cs +++ b/src/EpiserverImporter/Configuration.cs @@ -22,7 +22,7 @@ public int DegreesOfParallelism private bool GetBoolSetting(string key) { string setting = ConfigurationManager.AppSettings[key]; - return setting != null && setting.Equals(true.ToString(), StringComparison.CurrentCultureIgnoreCase); + return setting != null && setting.Equals(Boolean.TrueString, StringComparison.CurrentCultureIgnoreCase); } } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/ContentFolderCreator.cs b/src/EpiserverImporter/ContentFolderCreator.cs index 111595d..c2f5a45 100644 --- a/src/EpiserverImporter/ContentFolderCreator.cs +++ b/src/EpiserverImporter/ContentFolderCreator.cs @@ -17,8 +17,7 @@ public ContentFolderCreator(IContentRepository contentRepo) public ContentReference CreateOrGetFolder(ContentReference parent, string folderName) { - var existingFolder = _contentRepo.GetChildren(parent) - .FirstOrDefault(x => x.Name == folderName); + ContentFolder existingFolder = _contentRepo.GetChildren(parent).FirstOrDefault(x => x.Name == folderName); if (existingFolder != null) return existingFolder.ContentLink; @@ -28,4 +27,4 @@ public ContentReference CreateOrGetFolder(ContentReference parent, string folder return _contentRepo.Save(newFolder, SaveAction.Save, AccessLevel.NoAccess); } } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/EpiserverImporter.csproj b/src/EpiserverImporter/EpiserverImporter.csproj index 9f9b2db..cf95e08 100644 --- a/src/EpiserverImporter/EpiserverImporter.csproj +++ b/src/EpiserverImporter/EpiserverImporter.csproj @@ -33,7 +33,7 @@ - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\AjaxControlToolkit.dll + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\AjaxControlToolkit.dll ..\..\packages\AuthorizeNet.1.9.4\lib\AuthorizeNet.dll @@ -44,116 +44,107 @@ ..\..\packages\Castle.Windsor.4.1.0\lib\net45\Castle.Windsor.dll - - ..\..\packages\EPiServer.CMS.Core.11.2.1\lib\net461\EPiServer.dll + + ..\..\packages\EPiServer.CMS.Core.11.11.1\lib\net461\EPiServer.dll - - ..\..\packages\EPiServer.Framework.11.2.1\lib\net461\EPiServer.ApplicationModules.dll + + ..\..\packages\EPiServer.Framework.11.11.1\lib\net461\EPiServer.ApplicationModules.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\EPiServer.Business.Commerce.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\EPiServer.Business.Commerce.dll - - ..\..\packages\EPiServer.CMS.AspNet.11.2.1\lib\net461\EPiServer.Cms.AspNet.dll + + ..\..\packages\EPiServer.CMS.AspNet.11.11.1\lib\net461\EPiServer.Cms.AspNet.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\EPiServer.Commerce.Internal.Migration.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\EPiServer.Commerce.Internal.Migration.dll - - ..\..\packages\EPiServer.CMS.AspNet.11.2.1\lib\net461\EPiServer.Configuration.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\EPiServer.Commerce.Reporting.dll - - ..\..\packages\EPiServer.Framework.11.2.1\lib\net461\EPiServer.Data.dll + + ..\..\packages\EPiServer.CMS.AspNet.11.11.1\lib\net461\EPiServer.Configuration.dll - - ..\..\packages\EPiServer.Framework.11.2.1\lib\net461\EPiServer.Data.Cache.dll + + ..\..\packages\EPiServer.Framework.11.11.1\lib\net461\EPiServer.Data.dll - - ..\..\packages\EPiServer.CMS.Core.11.2.1\lib\net461\EPiServer.Enterprise.dll + + ..\..\packages\EPiServer.Framework.11.11.1\lib\net461\EPiServer.Data.Cache.dll - - ..\..\packages\EPiServer.Framework.11.2.1\lib\net461\EPiServer.Events.dll + + ..\..\packages\EPiServer.CMS.Core.11.11.1\lib\net461\EPiServer.Enterprise.dll - - ..\..\packages\EPiServer.Framework.11.2.1\lib\net461\EPiServer.Framework.dll + + ..\..\packages\EPiServer.Framework.11.11.1\lib\net461\EPiServer.Events.dll - - ..\..\packages\EPiServer.Framework.AspNet.11.2.1\lib\net461\EPiServer.Framework.AspNet.dll + + ..\..\packages\EPiServer.Framework.11.11.1\lib\net461\EPiServer.Framework.dll - - ..\..\packages\EPiServer.CMS.AspNet.11.2.1\lib\net461\EPiServer.ImageLibrary.dll + + ..\..\packages\EPiServer.Framework.AspNet.11.11.1\lib\net461\EPiServer.Framework.AspNet.dll - - ..\..\packages\EPiServer.Framework.11.2.1\lib\net461\EPiServer.Licensing.dll + + ..\..\packages\EPiServer.CMS.AspNet.11.11.1\lib\net461\EPiServer.ImageLibrary.dll - - ..\..\packages\EPiServer.CMS.Core.11.2.1\lib\net461\EPiServer.LinkAnalyzer.dll + + ..\..\packages\EPiServer.Framework.11.11.1\lib\net461\EPiServer.Licensing.dll - - ..\..\packages\EPiServer.Logging.Log4Net.2.2.0\lib\net461\EPiServer.Logging.Log4Net.dll + + ..\..\packages\EPiServer.CMS.Core.11.11.1\lib\net461\EPiServer.LinkAnalyzer.dll - - ..\..\packages\EPiServer.ServiceLocation.StructureMap.2.0.0\lib\net461\EPiServer.ServiceLocation.StructureMap.dll - - - ..\..\packages\EPiServer.CMS.AspNet.11.2.1\lib\net461\EPiServer.Web.WebControls.dll + + ..\..\packages\EPiServer.CMS.AspNet.11.11.1\lib\net461\EPiServer.Web.WebControls.dll ..\..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll - - ..\..\packages\log4net.2.0.8\lib\net45-full\log4net.dll - ..\..\packages\Lucene.Net.3.0.3\lib\NET40\Lucene.Net.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.BusinessFoundation.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.BusinessFoundation.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.BusinessFoundation.Data.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.BusinessFoundation.Data.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.Commerce.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.Commerce.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.Commerce.Marketing.Validators.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.Commerce.Plugins.Payment.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.Commerce.Plugins.Payment.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.Commerce.Plugins.Shipping.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.Commerce.Plugins.Shipping.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.Commerce.Website.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.Commerce.Website.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.Commerce.Workflow.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.Commerce.Workflow.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.DataProvider.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.DataProvider.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.FileUploader.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.FileUploader.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.MetaDataPlus.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.MetaDataPlus.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.Search.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.Search.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.Search.Extensions.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.Search.Extensions.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.Search.LuceneSearchProvider.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.Search.LuceneSearchProvider.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.SqlDataProvider.dll - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.SqlDataProvider.dll - - - ..\..\packages\EPiServer.Commerce.Core.11.5.0\lib\net461\Mediachase.WebConsoleLib.dll + + ..\..\packages\EPiServer.Commerce.Core.13.0.0\lib\net461\Mediachase.WebConsoleLib.dll ..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll @@ -162,12 +153,6 @@ ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - - ..\..\packages\StructureMap.4.5.2\lib\net45\StructureMap.dll - - - ..\..\packages\structuremap.web.4.0.0.315\lib\net40\StructureMap.Web.dll - ..\..\packages\System.ComponentModel.Annotations.4.4.0\lib\net461\System.ComponentModel.Annotations.dll @@ -192,8 +177,8 @@ ..\..\packages\System.Security.AccessControl.4.4.0\lib\net461\System.Security.AccessControl.dll - - ..\..\packages\System.Security.Cryptography.Xml.4.4.0\lib\net461\System.Security.Cryptography.Xml.dll + + ..\..\packages\System.Security.Cryptography.Xml.4.4.2\lib\net461\System.Security.Cryptography.Xml.dll ..\..\packages\System.Security.Permissions.4.4.0\lib\net461\System.Security.Permissions.dll @@ -209,6 +194,9 @@ True + + ..\..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll + @@ -276,15 +264,4 @@ - - - - - \ No newline at end of file diff --git a/src/EpiserverImporter/EpiserverImporter.nuspec b/src/EpiserverImporter/EpiserverImporter.nuspec index fbca000..f0135c7 100644 --- a/src/EpiserverImporter/EpiserverImporter.nuspec +++ b/src/EpiserverImporter/EpiserverImporter.nuspec @@ -14,9 +14,9 @@ Copyright © Epinova 2017 EPiServer Epinova inRiver PIM Commerce - - - + + + diff --git a/src/EpiserverImporter/EventHandling/ICatalogImporterHandler.cs b/src/EpiserverImporter/EventHandling/ICatalogImporterHandler.cs index 9d46d5e..72fb666 100644 --- a/src/EpiserverImporter/EventHandling/ICatalogImporterHandler.cs +++ b/src/EpiserverImporter/EventHandling/ICatalogImporterHandler.cs @@ -5,16 +5,16 @@ namespace Epinova.InRiverConnector.EpiserverImporter.EventHandling public interface ICatalogImportHandler { /// - /// Called before the Catalog XML is imported into Commerce + /// Called after the Catalog XML has been imported into Commerce /// - /// If any implementation throws an exception, the catalog will not be imported /// - void PreImport(XDocument catalog); + void PostImport(XDocument catalog); /// - /// Called after the Catalog XML has been imported into Commerce + /// Called before the Catalog XML is imported into Commerce /// + /// If any implementation throws an exception, the catalog will not be imported /// - void PostImport(XDocument catalog); + void PreImport(XDocument catalog); } } diff --git a/src/EpiserverImporter/EventHandling/IDeleteActionsHandler.cs b/src/EpiserverImporter/EventHandling/IDeleteActionsHandler.cs index 419014c..883fcc4 100644 --- a/src/EpiserverImporter/EventHandling/IDeleteActionsHandler.cs +++ b/src/EpiserverImporter/EventHandling/IDeleteActionsHandler.cs @@ -5,20 +5,20 @@ namespace Epinova.InRiverConnector.EpiserverImporter.EventHandling { public interface IDeleteActionsHandler { - void PreDeleteCatalog(int catalogId); - void PostDeleteCatalog(int catalogId); - void PreDeleteCatalogNode(NodeContent node); + void PostDeleteCatalogEntry(EntryContentBase deletedEntry); void PostDeleteCatalogNode(NodeContent node); + void PostDeleteResource(InRiverImportResource resource); + + void PreDeleteCatalog(int catalogId); + void PreDeleteCatalogEntry(EntryContentBase entry); - void PostDeleteCatalogEntry(EntryContentBase deletedEntry); + void PreDeleteCatalogNode(NodeContent node); void PreDeleteResource(InRiverImportResource resource); - - void PostDeleteResource(InRiverImportResource resource); } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/EventHandling/IInRiverEventsHandler.cs b/src/EpiserverImporter/EventHandling/IInRiverEventsHandler.cs index f72b2c2..4aec8d7 100644 --- a/src/EpiserverImporter/EventHandling/IInRiverEventsHandler.cs +++ b/src/EpiserverImporter/EventHandling/IInRiverEventsHandler.cs @@ -5,18 +5,18 @@ namespace Epinova.InRiverConnector.EpiserverImporter.EventHandling public interface IInRiverEventsHandler { /// - /// Called when an import or updated of data into Commerce are done. + /// Called when a delete of data has been committed in Commerce. /// /// The name of the catalog /// Which connector event that was the origin - /// if resources was in included in the import/update - void ImportUpdateCompleted(string catalogName, ImportUpdateCompletedEventType eventType, bool resourceIncluded); + void DeleteCompleted(string catalogName, DeleteCompletedEventType eventType); /// - /// Called when a delete of data has been committed in Commerce. + /// Called when an import or updated of data into Commerce are done. /// /// The name of the catalog /// Which connector event that was the origin - void DeleteCompleted(string catalogName, DeleteCompletedEventType eventType); + /// if resources was in included in the import/update + void ImportUpdateCompleted(string catalogName, ImportUpdateCompletedEventType eventType, bool resourceIncluded); } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/EventHandling/IResourceImporterHandler.cs b/src/EpiserverImporter/EventHandling/IResourceImporterHandler.cs index f001a81..09fe584 100644 --- a/src/EpiserverImporter/EventHandling/IResourceImporterHandler.cs +++ b/src/EpiserverImporter/EventHandling/IResourceImporterHandler.cs @@ -6,16 +6,16 @@ namespace Epinova.InRiverConnector.EpiserverImporter.EventHandling public interface IResourceImporterHandler { /// - /// Called before the Resources is imported into Commerce + /// Called after the Resource has been imported into Commerce /// - /// If any implementation throws an exception, the resources will not be imported /// - void PreImport(List resources); + void PostImport(List resources); /// - /// Called after the Resource has been imported into Commerce + /// Called before the Resources is imported into Commerce /// + /// If any implementation throws an exception, the resources will not be imported /// - void PostImport(List resources); + void PreImport(List resources); } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/ICatalogImporter.cs b/src/EpiserverImporter/ICatalogImporter.cs index c3d2162..b29a2c3 100644 --- a/src/EpiserverImporter/ICatalogImporter.cs +++ b/src/EpiserverImporter/ICatalogImporter.cs @@ -5,14 +5,14 @@ namespace Epinova.InRiverConnector.EpiserverImporter { public interface ICatalogImporter { - void ImportCatalogXml([FromBody] string path); - bool ImportUpdateCompleted(ImportUpdateCompletedData data); - void MoveNodeToRootIfNeeded(string catalogNodeId); - void DeleteCatalogEntry(string code); + void DeleteAssociation(string sourceCode, string targetCode); void DeleteCatalog(int catalogId); + void DeleteCatalogEntry(string code); void DeleteCatalogNode(string code); bool DeleteCompleted(DeleteCompletedData data); void DeleteRelation(string sourceCode, string targetCode); - void DeleteAssociation(string sourceCode, string targetCode); + void ImportCatalogXml([FromBody] string path); + bool ImportUpdateCompleted(ImportUpdateCompletedData data); + void MoveNodeToRootIfNeeded(string catalogNodeId); } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/ICatalogService.cs b/src/EpiserverImporter/ICatalogService.cs index 10f0931..5d78981 100644 --- a/src/EpiserverImporter/ICatalogService.cs +++ b/src/EpiserverImporter/ICatalogService.cs @@ -9,4 +9,4 @@ public interface ICatalogService IEnumerable GetChildren(EntryContentBase product); IEnumerable GetParents(EntryContentBase variant); } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/ImportStatusContainer.cs b/src/EpiserverImporter/ImportStatusContainer.cs index c701b1f..aa73a24 100644 --- a/src/EpiserverImporter/ImportStatusContainer.cs +++ b/src/EpiserverImporter/ImportStatusContainer.cs @@ -10,8 +10,8 @@ private ImportStatusContainer() public static ImportStatusContainer Instance => _instance ?? (_instance = new ImportStatusContainer()); - public string Message { get; set; } - public bool IsImporting { get; set; } + + public string Message { get; set; } } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/InriverDataImportController.cs b/src/EpiserverImporter/InriverDataImportController.cs index 6e33347..0a502db 100644 --- a/src/EpiserverImporter/InriverDataImportController.cs +++ b/src/EpiserverImporter/InriverDataImportController.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using System.Web.Http; -using System.Xml; -using System.Xml.Serialization; using Epinova.InRiverConnector.Interfaces; -using Epinova.InRiverConnector.Interfaces.Poco; using EPiServer.Logging; using EPiServer.ServiceLocation; @@ -27,25 +23,20 @@ public InriverDataImportController() } public InriverDataImportController(ICatalogImporter catalogImporter, - ILogger logger, - MediaImporter mediaImporter) + ILogger logger, + MediaImporter mediaImporter) { _catalogImporter = catalogImporter; _logger = logger; _mediaImporter = mediaImporter; } - - [HttpGet] - public string IsImporting() - { - _logger.Debug("IsImporting"); - if (ImportStatusContainer.Instance.IsImporting) - { - return ImportStatus.IsImporting; - } + [HttpPost] + public void DeleteCatalog([FromBody] int catalogId) + { + _logger.Debug("DeleteCatalog"); - return ImportStatusContainer.Instance.Message; + _catalogImporter.DeleteCatalog(catalogId); } [HttpPost] @@ -53,20 +44,12 @@ public void DeleteCatalogEntry(DeleteRequest request) { _logger.Debug("DeleteCatalogEntry"); - foreach (var code in request.Codes) + foreach (string code in request.Codes) { _catalogImporter.DeleteCatalogEntry(code); } } - [HttpPost] - public void DeleteCatalog([FromBody] int catalogId) - { - _logger.Debug("DeleteCatalog"); - - _catalogImporter.DeleteCatalog(catalogId); - } - [HttpPost] public void DeleteCatalogNode([FromBody] string catalogNodeId) { @@ -76,18 +59,9 @@ public void DeleteCatalogNode([FromBody] string catalogNodeId) } [HttpPost] - public void MoveNodeToRootIfNeeded([FromBody] string catalogNodeId) - { - _logger.Debug("MoveNodeToRootIfNeeded"); - - _catalogImporter.MoveNodeToRootIfNeeded(catalogNodeId); - } - - [HttpPost] - public void DeleteResource(DeleteResourceRequest request) + public void DeleteCompleted(DeleteCompletedData data) { - _logger.Debug($"DeleteResource with ID {request.ResourceGuid}"); - DoWithErrorHandling(() => _mediaImporter.DeleteResource(request)); + DoWithErrorHandling(() => _catalogImporter.DeleteCompleted(data)); } [HttpPost] @@ -104,6 +78,13 @@ public void DeleteLink(DeleteLinkRequest request) ); } + [HttpPost] + public void DeleteResource(DeleteResourceRequest request) + { + _logger.Debug($"DeleteResource with ID {request.ResourceGuid}"); + DoWithErrorHandling(() => _mediaImporter.DeleteResource(request)); + } + public string Get() { _logger.Debug("Hello from Episerver import controller!"); @@ -133,7 +114,7 @@ public string ImportResources(ImportResourcesRequest request) _mediaImporter.ImportResources(request); ImportStatusContainer.Instance.IsImporting = false; - ImportStatusContainer.Instance.Message = "Import Sucessful"; + ImportStatusContainer.Instance.Message = "Import Successful"; }); }); return ImportStatusContainer.Instance.Message; @@ -145,10 +126,25 @@ public bool ImportUpdateCompleted(ImportUpdateCompletedData data) return _catalogImporter.ImportUpdateCompleted(data); } + [HttpGet] + public string IsImporting() + { + _logger.Debug("IsImporting"); + + if (ImportStatusContainer.Instance.IsImporting) + { + return ImportStatus.IsImporting; + } + + return ImportStatusContainer.Instance.Message; + } + [HttpPost] - public void DeleteCompleted(DeleteCompletedData data) + public void MoveNodeToRootIfNeeded([FromBody] string catalogNodeId) { - DoWithErrorHandling(() => _catalogImporter.DeleteCompleted(data)); + _logger.Debug("MoveNodeToRootIfNeeded"); + + _catalogImporter.MoveNodeToRootIfNeeded(catalogNodeId); } private void DoWithErrorHandling(Action action) @@ -163,4 +159,4 @@ private void DoWithErrorHandling(Action action) } } } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/MediaImporter.cs b/src/EpiserverImporter/MediaImporter.cs index e1f8d4e..9491fc9 100644 --- a/src/EpiserverImporter/MediaImporter.cs +++ b/src/EpiserverImporter/MediaImporter.cs @@ -1,14 +1,12 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Configuration; using System.IO; using System.Linq; -using System.Text; +using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Serialization; -using Castle.Components.DictionaryAdapter; using Epinova.InRiverConnector.EpiserverImporter.EventHandling; using Epinova.InRiverConnector.EpiserverImporter.ResourceModels; using Epinova.InRiverConnector.Interfaces; @@ -32,25 +30,24 @@ namespace Epinova.InRiverConnector.EpiserverImporter { public class MediaImporter { - private readonly ILogger _logger; - private readonly IContentTypeRepository _contentTypeRepository; - private readonly ContentFolderCreator _contentFolderCreator; + private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1); private readonly IBlobFactory _blobFactory; + private readonly Configuration _config; + private readonly ContentFolderCreator _contentFolderCreator; private readonly ContentMediaResolver _contentMediaResolver; private readonly IContentRepository _contentRepository; + private readonly IContentTypeRepository _contentTypeRepository; + private readonly ILogger _logger; private readonly ReferenceConverter _referenceConverter; - private readonly Configuration _config; - private readonly IUrlSegmentGenerator _urlSegmentGenerator; public MediaImporter(ILogger logger, - IContentTypeRepository contentTypeRepository, - ContentFolderCreator contentFolderCreator, - IBlobFactory blobFactory, - ContentMediaResolver contentMediaResolver, - IContentRepository contentRepository, - ReferenceConverter referenceConverter, - Configuration config, - IUrlSegmentGenerator urlSegmentGenerator) + IContentTypeRepository contentTypeRepository, + ContentFolderCreator contentFolderCreator, + IBlobFactory blobFactory, + ContentMediaResolver contentMediaResolver, + IContentRepository contentRepository, + ReferenceConverter referenceConverter, + Configuration config) { _logger = logger; _contentTypeRepository = contentTypeRepository; @@ -60,9 +57,49 @@ public MediaImporter(ILogger logger, _contentRepository = contentRepository; _referenceConverter = referenceConverter; _config = config; - _urlSegmentGenerator = urlSegmentGenerator; } - + + public void DeleteResource(DeleteResourceRequest request) + { + if (!_contentRepository.TryGet(request.ResourceGuid, out MediaData mediaData)) + { + _logger.Information($"Deleting resource with Guid {request.ResourceGuid}. Resource not found."); + return; + } + + List references = + _contentRepository.GetReferencesToContent(mediaData.ContentLink, false).ToList(); + + if (request.EntryToRemoveFrom == null) + { + _logger.Debug($"Deleting resource with GUID {request.ResourceGuid}"); + _logger.Debug($"Found {references.Count} references to mediacontent."); + + foreach (string code in references + .Select(reference => _referenceConverter.GetCode(reference.OwnerID))) + { + DeleteMediaLink(mediaData, code); + } + + _contentRepository.Delete(mediaData.ContentLink, true, AccessLevel.NoAccess); + } + else + { + foreach (ReferenceInformation reference in references) + { + if (_contentRepository.TryGet(reference.OwnerID, out EntryContentBase content)) + { + if (content.Code != request.EntryToRemoveFrom) + continue; + } + + _logger.Debug($"Removing resource {request.ResourceGuid} from entry with code {content.Code}."); + + DeleteMediaLink(mediaData, content.Code); + } + } + } + public void ImportResources(ImportResourcesRequest request) { @@ -71,10 +108,11 @@ public void ImportResources(ImportResourcesRequest request) return; _logger.Debug($"Starting import of {resources.Count} resources."); - + try { - var importerHandlers = ServiceLocator.Current.GetAllInstances().ToList(); + List importerHandlers = + ServiceLocator.Current.GetAllInstances().ToList(); if (_config.RunResourceImporterHandlers) { @@ -84,8 +122,8 @@ public void ImportResources(ImportResourcesRequest request) } } - var errors = 0; - + int errors = 0; + // TODO: Degree of parallelism should be configurable, default to 2. Parallel.ForEach(resources, new ParallelOptions { MaxDegreeOfParallelism = _config.DegreesOfParallelism }, resource => { @@ -116,19 +154,185 @@ public void ImportResources(ImportResourcesRequest request) } } + /// + /// Returns a reference to the inriver resource folder. It will be created if it does not already exist. + /// + /// + /// + protected ContentReference GetFolder(FileInfo fileInfo, ContentType contentType) + { + return ExecuteWithinLock(() => + { + string rootFolderName = ConfigurationManager.AppSettings["InRiverConnector.ResourceFolderName"]; + ContentReference rootFolder = + _contentFolderCreator.CreateOrGetFolder(SiteDefinition.Current.GlobalAssetsRoot, rootFolderName ?? "ImportedResources"); + + string firstLevelFolderName = fileInfo.Name[0].ToString().ToUpper(); + ContentReference firstLevelFolder = _contentFolderCreator.CreateOrGetFolder(rootFolder, firstLevelFolderName); + + string secondLevelFolderName = contentType.Name.Replace("File", ""); + return _contentFolderCreator.CreateOrGetFolder(firstLevelFolder, secondLevelFolderName); + }); + } + + private void AddLinksFromMediaToCodes(IContent contentMedia, IEnumerable codes) + { + var media = new CommerceMedia { AssetLink = contentMedia.ContentLink, GroupName = "default", AssetType = "episerver.core.icontentmedia" }; + + foreach (EntryCode entryCode in codes) + { + ContentReference contentReference = _referenceConverter.GetContentLink(entryCode.Code); + + IAssetContainer writableContent = null; + if (_contentRepository.TryGet(contentReference, out EntryContentBase entry)) + writableContent = (EntryContentBase)entry.CreateWritableClone(); + + if (_contentRepository.TryGet(contentReference, out NodeContent node)) + writableContent = (NodeContent)node.CreateWritableClone(); + + if (writableContent == null) + { + _logger.Error($"Can't get a suitable content (with code {entryCode.Code} to add CommerceMedia to, meaning it's neither EntryContentBase nor NodeContent."); + continue; + } + + CommerceMedia existingMedia = writableContent.CommerceMediaCollection.FirstOrDefault(x => x.AssetLink.Equals(media.AssetLink)); + if (existingMedia != null) + writableContent.CommerceMediaCollection.Remove(existingMedia); + + if (entryCode.IsMainPicture) + { + _logger.Debug($"Setting '{contentMedia.Name}' as main media on {entryCode.Code}"); + media.SortOrder = 0; + writableContent.CommerceMediaCollection.Insert(0, media); + } + else + { + _logger.Debug($"Adding '{contentMedia.Name}' as media on {entryCode.Code}"); + media.SortOrder = 1; + writableContent.CommerceMediaCollection.Add(media); + } + + _contentRepository.Save((IContent)writableContent, SaveAction.Publish, AccessLevel.NoAccess); + } + } + + private MediaData CreateNewFile(InRiverImportResource inriverResource) + { + ResourceMetaField resourceFileId = inriverResource.MetaFields.FirstOrDefault(m => m.Id == "ResourceFileId"); + if (String.IsNullOrEmpty(resourceFileId?.Values.FirstOrDefault()?.Data)) + { + _logger.Debug("ResourceFileId is null, won't do stuff."); + return null; + } + + _logger.Debug($"Attempting to create and import file from path: {inriverResource.Path}"); + + var fileInfo = new FileInfo(inriverResource.Path); + + IEnumerable mediaTypes = _contentMediaResolver.ListAllMatching(fileInfo.Extension).ToList(); + + _logger.Debug($"Found {mediaTypes.Count()} matching media types for extension {fileInfo.Extension}."); + + Type contentTypeType = mediaTypes.FirstOrDefault(x => x.GetInterfaces().Contains(typeof(IInRiverResource))) ?? + _contentMediaResolver.GetFirstMatching(fileInfo.Extension); + + if (contentTypeType == null) + _logger.Warning($"Can't find suitable content type when trying to import {inriverResource.Path}"); + + else + _logger.Debug($"Chosen content type-type is {contentTypeType.Name}."); + + ContentType contentType = _contentTypeRepository.Load(contentTypeType); + + var newFile = _contentRepository.GetDefault(GetFolder(fileInfo, contentType), contentType.ID); + newFile.Name = fileInfo.Name; + newFile.ContentGuid = EpiserverEntryIdentifier.EntityIdToGuid(inriverResource.ResourceId); + + // ReSharper disable once SuspiciousTypeConversion.Global + if (newFile is IInRiverResource resource) + { + resource.ResourceFileId = Int32.Parse(resourceFileId.Values.First().Data); + resource.EntityId = inriverResource.ResourceId; + + try + { + resource.HandleMetaData(inriverResource.MetaFields); + } + catch (Exception exception) + { + _logger.Error($"Error when running HandleMetaData for resource {inriverResource.ResourceId} with contentType {contentType.Name}: {exception.Message}"); + } + } + + Blob blob = _blobFactory.CreateBlob(newFile.BinaryDataContainer, fileInfo.Extension); + using (Stream stream = blob.OpenWrite()) + { + FileStream fileStream = File.OpenRead(fileInfo.FullName); + fileStream.CopyTo(stream); + fileStream.Dispose(); + } + + newFile.BinaryData = blob; + + _logger.Debug($"New mediadata is ready to be saved: {newFile.Name}, from path {inriverResource.Path}"); + + ContentReference contentReference = _contentRepository.Save(newFile, SaveAction.Publish, AccessLevel.NoAccess); + var mediaData = _contentRepository.Get(contentReference); + + _logger.Debug($"Saved file {fileInfo.Name} with Content ID {contentReference?.ID}."); + + return mediaData; + } + + private void DeleteLinksBetweenMediaAndCodes(MediaData media, IEnumerable codes) + { + foreach (string code in codes) + { + DeleteMediaLink(media, code); + } + } + + /// The media to remove as link + /// The code of the catalog content from which the should be removed. + private void DeleteMediaLink(MediaData media, string code) + { + ContentReference contentReference = _referenceConverter.GetContentLink(code); + if (ContentReference.IsNullOrEmpty(contentReference)) + return; + + IAssetContainer writableContent = null; + if (_contentRepository.TryGet(contentReference, out NodeContent nodeContent)) + { + writableContent = nodeContent.CreateWritableClone(); + } + else if (_contentRepository.TryGet(contentReference, out EntryContentBase catalogEntry)) + { + writableContent = catalogEntry.CreateWritableClone(); + } + + writableContent?.CommerceMediaCollection.CreateWritableClone(); + CommerceMedia mediaToRemove = writableContent?.CommerceMediaCollection?.FirstOrDefault(x => x.AssetLink.Equals(media.ContentLink)); + if (mediaToRemove == null) + return; + + writableContent.CommerceMediaCollection.Remove(mediaToRemove); + _contentRepository.Save((IContent)writableContent, SaveAction.Publish, AccessLevel.NoAccess); + } + private List DeserializeRequest(ImportResourcesRequest request) { _logger.Debug($"Deserializing and preparing {request.ResourceXmlPath} for import."); var serializer = new XmlSerializer(typeof(Resources)); Resources resources; - using (var reader = XmlReader.Create(request.ResourceXmlPath)) + using (XmlReader reader = XmlReader.Create(request.ResourceXmlPath)) { resources = (Resources)serializer.Deserialize(reader); } var resourcesForImport = new List(); - foreach (var resource in resources.ResourceFiles.Resource) + foreach (Resource resource in resources.ResourceFiles.Resource) { var newRes = new InRiverImportResource { @@ -137,9 +341,9 @@ private List DeserializeRequest(ImportResourcesRequest re if (resource.ParentEntries?.EntryCode != null) { - foreach (var entryCode in resource.ParentEntries.EntryCode) + foreach (Interfaces.Poco.EntryCode entryCode in resource.ParentEntries.EntryCode) { - if (string.IsNullOrEmpty(entryCode.Value)) + if (String.IsNullOrEmpty(entryCode.Value)) continue; newRes.Codes.Add(entryCode.Value); @@ -158,7 +362,7 @@ private List DeserializeRequest(ImportResourcesRequest re // path is ".\some file.ext" if (resource.Paths?.Path != null) { - var filePath = resource.Paths.Path.Value.Remove(0, 1); + string filePath = resource.Paths.Path.Value.Remove(0, 1); filePath = filePath.Replace("/", "\\"); newRes.Path = request.BasePath + filePath; } @@ -171,28 +375,46 @@ private List DeserializeRequest(ImportResourcesRequest re return resourcesForImport; } + private T ExecuteWithinLock(Func action, string errorString = null) + { + Semaphore.Wait(); + try + { + return action(); + } + catch (Exception exception) + { + _logger.Error(errorString, exception); + throw; + } + finally + { + Semaphore.Release(); + } + } + private List GenerateMetaFields(Resource resource) { - List metaFields = new List(); + var metaFields = new List(); if (resource.ResourceFields == null) return metaFields; - foreach (var metaField in resource.ResourceFields.MetaField) + foreach (MetaField metaField in resource.ResourceFields.MetaField) { var resourceMetaField = new ResourceMetaField { Id = metaField.Name.Value }; var values = new List(); - foreach (var data in metaField.Data) + foreach (Data data in metaField.Data) { - Value value = new Value { Languagecode = data.language }; + var value = new Value { Languagecode = data.language }; if (data.Item != null && data.Item.Count > 0) { - foreach (var item in data.Item) + foreach (Item item in data.Item) { value.Data += item.value + ";"; } - var lastIndexOf = value.Data.LastIndexOf(';'); + int lastIndexOf = value.Data.LastIndexOf(';'); if (lastIndexOf != -1) { value.Data = value.Data.Remove(lastIndexOf); @@ -214,65 +436,47 @@ private List GenerateMetaFields(Resource resource) return metaFields; } - - private void ImportResource(InRiverImportResource resource) + private void HandleDelete(InRiverImportResource inriverResource) { - if (resource.Action == ImporterActions.Added || resource.Action == ImporterActions.Updated) - { - ImportImageAndAttachToEntry(resource); - } - else if (resource.Action == ImporterActions.Deleted) - { - _logger.Debug($"Got delete action for resource id: {resource.ResourceId}."); - HandleDelete(resource); - } - else if (resource.Action == ImporterActions.Unlinked) - { - HandleUnlink(resource); - } - } + var existingMediaData = _contentRepository.Get(EpiserverEntryIdentifier.EntityIdToGuid(inriverResource.ResourceId)); - public void DeleteResource(DeleteResourceRequest request) - { - var mediaData = _contentRepository.Get(request.ResourceGuid); - var references = _contentRepository.GetReferencesToContent(mediaData.ContentLink, false).ToList(); + List importerHandlers = ServiceLocator.Current.GetAllInstances().ToList(); - if (request.EntryToRemoveFrom == null) + if (_config.RunDeleteActionsHandlers) { - _logger.Debug($"Deleting resource with GUID {request.ResourceGuid}"); - _logger.Debug($"Found {references.Count} references to mediacontent."); - - foreach (var reference in references) + foreach (IDeleteActionsHandler handler in importerHandlers) { - var code = _referenceConverter.GetCode(reference.OwnerID); - DeleteMediaLink(mediaData, code); + handler.PreDeleteResource(inriverResource); } - _contentRepository.Delete(mediaData.ContentLink, true, AccessLevel.NoAccess); } - else + + _contentRepository.Delete(existingMediaData.ContentLink, true, AccessLevel.NoAccess); + + if (_config.RunDeleteActionsHandlers) { - foreach (var reference in references) + foreach (IDeleteActionsHandler handler in importerHandlers) { - if (_contentRepository.TryGet(reference.OwnerID, out EntryContentBase content)) - { - if (content.Code != request.EntryToRemoveFrom) - continue; - } - _logger.Debug($"Removing resource {request.ResourceGuid} from entry with code {content.Code}."); - - DeleteMediaLink(mediaData, content.Code); + handler.PostDeleteResource(inriverResource); } } } + private void HandleUnlink(InRiverImportResource inriverResource) + { + var existingMediaData = _contentRepository.Get(EpiserverEntryIdentifier.EntityIdToGuid(inriverResource.ResourceId)); + + DeleteLinksBetweenMediaAndCodes(existingMediaData, inriverResource.Codes); + } + private void ImportImageAndAttachToEntry(InRiverImportResource inriverResource) { - var mediaGuid = EpiserverEntryIdentifier.EntityIdToGuid(inriverResource.ResourceId); + Guid mediaGuid = EpiserverEntryIdentifier.EntityIdToGuid(inriverResource.ResourceId); if (_contentRepository.TryGet(mediaGuid, out MediaData existingMediaData)) { _logger.Debug($"Found existing resource with Resource ID: {inriverResource.ResourceId}"); - UpdateMetaData((IInRiverResource) existingMediaData, inriverResource); + // ReSharper disable once SuspiciousTypeConversion.Global + UpdateMetaData((IInRiverResource)existingMediaData, inriverResource); if (inriverResource.Action == ImporterActions.Added) { @@ -289,58 +493,35 @@ private void ImportImageAndAttachToEntry(InRiverImportResource inriverResource) } } - private void AddLinksFromMediaToCodes(MediaData contentMedia, List codes) + + private void ImportResource(InRiverImportResource resource) { - var media = new CommerceMedia { AssetLink = contentMedia.ContentLink, GroupName = "default", AssetType = "episerver.core.icontentmedia" }; - - foreach (EntryCode entryCode in codes) + if (resource.Action == ImporterActions.Added || resource.Action == ImporterActions.Updated) { - var contentReference = _referenceConverter.GetContentLink(entryCode.Code); - - IAssetContainer writableContent = null; - if (_contentRepository.TryGet(contentReference, out EntryContentBase entry)) - writableContent = (EntryContentBase) entry.CreateWritableClone(); - - if (_contentRepository.TryGet(contentReference, out NodeContent node)) - writableContent = (NodeContent)node.CreateWritableClone(); - - if (writableContent == null) - { - _logger.Error($"Can't get a suitable content (with code {entryCode.Code} to add CommerceMedia to, meaning it's neither EntryContentBase nor NodeContent."); - continue; - } - - var existingMedia = writableContent.CommerceMediaCollection.FirstOrDefault(x => x.AssetLink.Equals(media.AssetLink)); - if (existingMedia != null) - writableContent.CommerceMediaCollection.Remove(existingMedia); - - if (entryCode.IsMainPicture) - { - _logger.Debug($"Setting '{contentMedia.Name}' as main media on {entryCode.Code}"); - media.SortOrder = 0; - writableContent.CommerceMediaCollection.Insert(0, media); - } - else - { - _logger.Debug($"Adding '{contentMedia.Name}' as media on {entryCode.Code}"); - media.SortOrder = 1; - writableContent.CommerceMediaCollection.Add(media); - } - - _contentRepository.Save((IContent) writableContent, SaveAction.Publish, AccessLevel.NoAccess); + ImportImageAndAttachToEntry(resource); + } + else if (resource.Action == ImporterActions.Deleted) + { + _logger.Debug($"Got delete action for resource id: {resource.ResourceId}."); + HandleDelete(resource); + } + else if (resource.Action == ImporterActions.Unlinked) + { + HandleUnlink(resource); } } private void UpdateMetaData(IInRiverResource resource, InRiverImportResource updatedResource) { - MediaData editableMediaData = (MediaData)((MediaData)resource).CreateWritableClone(); + // ReSharper disable once SuspiciousTypeConversion.Global + var editableMediaData = (MediaData)((MediaData)resource).CreateWritableClone(); ResourceMetaField resourceFileId = updatedResource.MetaFields.FirstOrDefault(m => m.Id == "ResourceFileId"); - if (resourceFileId != null && !string.IsNullOrEmpty(resourceFileId.Values.First().Data) && resource.ResourceFileId != int.Parse(resourceFileId.Values.First().Data)) + if (resourceFileId != null && !String.IsNullOrEmpty(resourceFileId.Values.First().Data) && resource.ResourceFileId != Int32.Parse(resourceFileId.Values.First().Data)) { - IBlobFactory blobFactory = ServiceLocator.Current.GetInstance(); + var blobFactory = ServiceLocator.Current.GetInstance(); - FileInfo fileInfo = new FileInfo(updatedResource.Path); + var fileInfo = new FileInfo(updatedResource.Path); if (fileInfo.Exists == false) { throw new FileNotFoundException("File could not be imported", updatedResource.Path); @@ -353,168 +534,17 @@ private void UpdateMetaData(IInRiverResource resource, InRiverImportResource upd { FileStream fileStream = File.OpenRead(fileInfo.FullName); fileStream.CopyTo(s); + fileStream.Dispose(); } editableMediaData.BinaryData = blob; + editableMediaData.Name = fileInfo.Name; } - ((IInRiverResource) editableMediaData).HandleMetaData(updatedResource.MetaFields); + // ReSharper disable once SuspiciousTypeConversion.Global + ((IInRiverResource)editableMediaData).HandleMetaData(updatedResource.MetaFields); _contentRepository.Save(editableMediaData, SaveAction.Publish, AccessLevel.NoAccess); } - - private MediaData CreateNewFile(InRiverImportResource inriverResource) - { - ResourceMetaField resourceFileId = inriverResource.MetaFields.FirstOrDefault(m => m.Id == "ResourceFileId"); - if (string.IsNullOrEmpty(resourceFileId?.Values.FirstOrDefault()?.Data)) - { - _logger.Debug($"ResourceFileId is null, won't do stuff."); - return null; - } - - _logger.Debug($"Attempting to create and import file from path: {inriverResource.Path}"); - - var fileInfo = new FileInfo(inriverResource.Path); - - IEnumerable mediaTypes = _contentMediaResolver.ListAllMatching(fileInfo.Extension).ToList(); - - _logger.Debug($"Found {mediaTypes.Count()} matching media types for extension {fileInfo.Extension}."); - - var contentTypeType = mediaTypes.FirstOrDefault(x => x.GetInterfaces().Contains(typeof(IInRiverResource))) ?? - _contentMediaResolver.GetFirstMatching(fileInfo.Extension); - - if(contentTypeType == null) - _logger.Warning($"Can't find suitable content type when trying to import {inriverResource.Path}"); - - else - _logger.Debug($"Chosen content type-type is {contentTypeType.Name}."); - - var contentType = _contentTypeRepository.Load(contentTypeType); - - var newFile = _contentRepository.GetDefault(GetFolder(fileInfo, contentType), contentType.ID); - newFile.Name = fileInfo.Name; - newFile.ContentGuid = EpiserverEntryIdentifier.EntityIdToGuid(inriverResource.ResourceId); - - if (newFile is IInRiverResource resource) - { - resource.ResourceFileId = int.Parse(resourceFileId.Values.First().Data); - resource.EntityId = inriverResource.ResourceId; - - try - { - resource.HandleMetaData(inriverResource.MetaFields); - } - catch (Exception exception) - { - _logger.Error($"Error when running HandleMetaData for resource {inriverResource.ResourceId} with contentType {contentType.Name}: {exception.Message}"); - } - } - - var blob = _blobFactory.CreateBlob(newFile.BinaryDataContainer, fileInfo.Extension); - using (var stream = blob.OpenWrite()) - { - var fileStream = File.OpenRead(fileInfo.FullName); - fileStream.CopyTo(stream); - } - - newFile.BinaryData = blob; - - _logger.Debug($"New mediadata is ready to be saved: {newFile.Name}, from path {inriverResource.Path}"); - - var contentReference = _contentRepository.Save(newFile, SaveAction.Publish, AccessLevel.NoAccess); - var mediaData = _contentRepository.Get(contentReference); - - _logger.Debug($"Saved file {fileInfo.Name} with Content ID {contentReference?.ID}."); - - return mediaData; - } - - private void HandleUnlink(InRiverImportResource inriverResource) - { - var existingMediaData = _contentRepository.Get(EpiserverEntryIdentifier.EntityIdToGuid(inriverResource.ResourceId)); - - DeleteLinksBetweenMediaAndCodes(existingMediaData, inriverResource.Codes); - } - - private void HandleDelete(InRiverImportResource inriverResource) - { - var existingMediaData = _contentRepository.Get(EpiserverEntryIdentifier.EntityIdToGuid(inriverResource.ResourceId)); - - var importerHandlers = ServiceLocator.Current.GetAllInstances().ToList(); - - if (_config.RunDeleteActionsHandlers) - { - foreach (var handler in importerHandlers) - { - handler.PreDeleteResource(inriverResource); - } - } - - _contentRepository.Delete(existingMediaData.ContentLink, true, AccessLevel.NoAccess); - - if (_config.RunDeleteActionsHandlers) - { - foreach (IDeleteActionsHandler handler in importerHandlers) - { - handler.PostDeleteResource(inriverResource); - } - } - } - - private void DeleteLinksBetweenMediaAndCodes(MediaData media, IEnumerable codes) - { - foreach (var code in codes) - { - DeleteMediaLink(media, code); - } - } - - /// The media to remove as link - /// The code of the catalog content from which the should be removed. - private void DeleteMediaLink(MediaData media, string code) - { - var contentReference = _referenceConverter.GetContentLink(code); - if (ContentReference.IsNullOrEmpty(contentReference)) - return; - - IAssetContainer writableContent = null; - if (_contentRepository.TryGet(contentReference, out NodeContent nodeContent)) - { - writableContent = nodeContent.CreateWritableClone(); - } - else if (_contentRepository.TryGet(contentReference, out EntryContentBase catalogEntry)) - { - writableContent = catalogEntry.CreateWritableClone(); - } - - var writableMediaCollection = writableContent.CommerceMediaCollection.CreateWritableClone(); - var mediaToRemove = writableContent.CommerceMediaCollection.FirstOrDefault(x => x.AssetLink.Equals(media.ContentLink)); - if (mediaToRemove == null) - return; - - writableContent.CommerceMediaCollection.Remove(mediaToRemove); - _contentRepository.Save((IContent) writableContent, SaveAction.Publish, AccessLevel.NoAccess); - } - - private static readonly object LockObject = new object(); - - /// - /// Returns a reference to the inriver resource folder. It will be created if it does not already exist. - /// - /// - /// - protected ContentReference GetFolder(FileInfo fileInfo, ContentType contentType) - { - lock(LockObject) { - var rootFolderName = ConfigurationManager.AppSettings["InRiverConnector.ResourceFolderName"]; - var rootFolder = _contentFolderCreator.CreateOrGetFolder(SiteDefinition.Current.GlobalAssetsRoot, rootFolderName ?? "ImportedResources"); - - var firstLevelFolderName = fileInfo.Name[0].ToString().ToUpper(); - var firstLevelFolder = _contentFolderCreator.CreateOrGetFolder(rootFolder, firstLevelFolderName); - - var secondLevelFolderName = contentType.Name.Replace("File", ""); - return _contentFolderCreator.CreateOrGetFolder(firstLevelFolder, secondLevelFolderName); - } - } } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/Properties/AssemblyInfo.cs b/src/EpiserverImporter/Properties/AssemblyInfo.cs index 8e2fca9..da47ac4 100644 --- a/src/EpiserverImporter/Properties/AssemblyInfo.cs +++ b/src/EpiserverImporter/Properties/AssemblyInfo.cs @@ -1,10 +1,6 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. [assembly: AssemblyTitle("Epinova.InRiverConnector")] [assembly: AssemblyDescription("Connector between Episerver and inRiver PIM")] [assembly: AssemblyCompany("")] @@ -12,29 +8,12 @@ [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("2430f1d5-a27a-4b7c-8eca-2bd60a70eaba")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.3.0.0")] -[assembly: AssemblyFileVersion("1.3.0.0")] +[assembly: AssemblyVersion("1.4.0.0")] +[assembly: AssemblyFileVersion("1.4.0.0")] #if DEBUG [assembly: AssemblyConfiguration("Debug")] #else [assembly: AssemblyConfiguration("Release")] -#endif \ No newline at end of file +#endif diff --git a/src/EpiserverImporter/PublisherInitializer.cs b/src/EpiserverImporter/PublisherInitializer.cs index 50d3859..aa330a4 100644 --- a/src/EpiserverImporter/PublisherInitializer.cs +++ b/src/EpiserverImporter/PublisherInitializer.cs @@ -2,24 +2,30 @@ using EPiServer.Framework; using EPiServer.Framework.Initialization; using EPiServer.ServiceLocation; +using InitializationModule = EPiServer.Web.InitializationModule; namespace Epinova.InRiverConnector.EpiserverImporter { [InitializableModule] - [ModuleDependency(typeof(EPiServer.Web.InitializationModule))] + [ModuleDependency(typeof(InitializationModule))] public class PublisherInitializer : IConfigurableModule { + public void ConfigureContainer(ServiceConfigurationContext context) + { + context.Services.AddTransient(); + context.Services.AddTransient(); + } + /// - /// Initializate the inRiver Web API. + /// Initialize the inRiver Web API. /// /// /// This method is called once after CMS has been initialized /// - /// public void Initialize(InitializationEngine context) { - var config = GlobalConfiguration.Configuration; - + HttpConfiguration config = GlobalConfiguration.Configuration; + //// For debug purposes, turn this on. This should be done in the web project //// and not in a packaged library. config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; @@ -29,22 +35,8 @@ public void Initialize(InitializationEngine context) new { id = RouteParameter.Optional }); } - public void Preload(string[] parameters) - { - } - public void Uninitialize(InitializationEngine context) { } - - public void ConfigureContainer(ServiceConfigurationContext context) - { - context.StructureMap().Configure(x => - { - x.For().Use(); - x.For().Use(); - }); - } } - -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/ResourceModels/IInRiverResource.cs b/src/EpiserverImporter/ResourceModels/IInRiverResource.cs index fb478f8..2f575bd 100644 --- a/src/EpiserverImporter/ResourceModels/IInRiverResource.cs +++ b/src/EpiserverImporter/ResourceModels/IInRiverResource.cs @@ -6,10 +6,10 @@ namespace Epinova.InRiverConnector.EpiserverImporter.ResourceModels { public interface IInRiverResource : IContentData { - int ResourceFileId { get; set; } - int EntityId { get; set; } + int ResourceFileId { get; set; } + void HandleMetaData(List metaFields); } -} \ No newline at end of file +} diff --git a/src/EpiserverImporter/SecuredApiController.cs b/src/EpiserverImporter/SecuredApiController.cs index 429c134..b6ac53c 100644 --- a/src/EpiserverImporter/SecuredApiController.cs +++ b/src/EpiserverImporter/SecuredApiController.cs @@ -20,8 +20,8 @@ public override Task ExecuteAsync(HttpControllerContext con { if (!ValidateApiKey(controllerContext.Request)) { - HttpResponseMessage resp = new HttpResponseMessage(HttpStatusCode.Forbidden); - TaskCompletionSource tsc = new TaskCompletionSource(); + var resp = new HttpResponseMessage(HttpStatusCode.Forbidden); + var tsc = new TaskCompletionSource(); tsc.SetResult(resp); return tsc.Task; } @@ -31,7 +31,7 @@ public override Task ExecuteAsync(HttpControllerContext con protected virtual bool ValidateApiKey(HttpRequestMessage request) { - if (string.IsNullOrEmpty(ApiKeyValue)) + if (String.IsNullOrEmpty(ApiKeyValue)) return false; return request.Headers.GetValues(ApiKeyName).FirstOrDefault() == ApiKeyValue; diff --git a/src/EpiserverImporter/packages.config b/src/EpiserverImporter/packages.config index 7a34bee..908d61e 100644 --- a/src/EpiserverImporter/packages.config +++ b/src/EpiserverImporter/packages.config @@ -3,14 +3,11 @@ - - - - - - - - + + + + + @@ -23,15 +20,14 @@ - - - + + \ No newline at end of file diff --git a/src/Interfaces/DeleteCompletedData.cs b/src/Interfaces/DeleteCompletedData.cs index 5988478..ce62043 100644 --- a/src/Interfaces/DeleteCompletedData.cs +++ b/src/Interfaces/DeleteCompletedData.cs @@ -8,4 +8,4 @@ public class DeleteCompletedData public DeleteCompletedEventType EventType { get; set; } } -} \ No newline at end of file +} diff --git a/src/Interfaces/DeleteLinkRequest.cs b/src/Interfaces/DeleteLinkRequest.cs index e0ce92f..d753314 100644 --- a/src/Interfaces/DeleteLinkRequest.cs +++ b/src/Interfaces/DeleteLinkRequest.cs @@ -2,8 +2,8 @@ { public class DeleteLinkRequest { + public bool IsRelation { get; set; } public string SourceCode { get; set; } public string TargetCode { get; set; } - public bool IsRelation { get; set; } } -} \ No newline at end of file +} diff --git a/src/Interfaces/DeleteRequest.cs b/src/Interfaces/DeleteRequest.cs index f3df411..b8ea4d6 100644 --- a/src/Interfaces/DeleteRequest.cs +++ b/src/Interfaces/DeleteRequest.cs @@ -10,7 +10,7 @@ public DeleteRequest() public DeleteRequest(string code) { - Codes = new List {code}; + Codes = new List { code }; } public DeleteRequest(List codes) @@ -20,4 +20,4 @@ public DeleteRequest(List codes) public List Codes { get; set; } } -} \ No newline at end of file +} diff --git a/src/Interfaces/DeleteResourceRequest.cs b/src/Interfaces/DeleteResourceRequest.cs index c1abcf7..9fadf3d 100644 --- a/src/Interfaces/DeleteResourceRequest.cs +++ b/src/Interfaces/DeleteResourceRequest.cs @@ -4,8 +4,7 @@ namespace Epinova.InRiverConnector.Interfaces { public class DeleteResourceRequest { - public Guid ResourceGuid { get; set; } - public string EntryToRemoveFrom { get; set; } + public Guid ResourceGuid { get; set; } } -} \ No newline at end of file +} diff --git a/src/Interfaces/Enums/DeleteCompletedEventType.cs b/src/Interfaces/Enums/DeleteCompletedEventType.cs index 6aedda5..9a88bb0 100644 --- a/src/Interfaces/Enums/DeleteCompletedEventType.cs +++ b/src/Interfaces/Enums/DeleteCompletedEventType.cs @@ -6,4 +6,4 @@ public enum DeleteCompletedEventType EntitiyDeleted, LinkDeleted } -} \ No newline at end of file +} diff --git a/src/Interfaces/Enums/ImportUpdateCompletedEventType.cs b/src/Interfaces/Enums/ImportUpdateCompletedEventType.cs index d544c54..395afcd 100644 --- a/src/Interfaces/Enums/ImportUpdateCompletedEventType.cs +++ b/src/Interfaces/Enums/ImportUpdateCompletedEventType.cs @@ -9,4 +9,4 @@ public enum ImportUpdateCompletedEventType LinkAdded, LinkUpdated } -} \ No newline at end of file +} diff --git a/src/Interfaces/EpiserverEntryIdentifier.cs b/src/Interfaces/EpiserverEntryIdentifier.cs index 96e20be..fc32b04 100644 --- a/src/Interfaces/EpiserverEntryIdentifier.cs +++ b/src/Interfaces/EpiserverEntryIdentifier.cs @@ -4,12 +4,13 @@ namespace Epinova.InRiverConnector.Interfaces { public class EpiserverEntryIdentifier { - // INFO: Modifying the format of this will break all ties with existing catalog entries in Episerver. - // If this is changed, it has to be flagged as a MAJOR BREAKING CHANGE. - + /// + /// INFO: Modifying the format of this will break all ties with existing catalog entries in Episerver. + /// If this is changed, it has to be flagged as a MAJOR BREAKING CHANGE. + /// public static Guid EntityIdToGuid(int entityId) { return new Guid($"00000000-0000-0000-0000-00{entityId:0000000000}"); } } -} \ No newline at end of file +} diff --git a/src/Interfaces/ImportCatalogXmlRequest.cs b/src/Interfaces/ImportCatalogXmlRequest.cs index bbfdc8c..2c5ab34 100644 --- a/src/Interfaces/ImportCatalogXmlRequest.cs +++ b/src/Interfaces/ImportCatalogXmlRequest.cs @@ -4,4 +4,4 @@ public class ImportCatalogXmlRequest { public string Path { get; set; } } -} \ No newline at end of file +} diff --git a/src/Interfaces/ImportResourcesRequest.cs b/src/Interfaces/ImportResourcesRequest.cs index d936fb0..13671c9 100644 --- a/src/Interfaces/ImportResourcesRequest.cs +++ b/src/Interfaces/ImportResourcesRequest.cs @@ -3,8 +3,7 @@ public class ImportResourcesRequest { public string BasePath { get; set; } - + public string ResourceXmlPath { get; set; } - } -} \ No newline at end of file +} diff --git a/src/Interfaces/ImportStatus.cs b/src/Interfaces/ImportStatus.cs index 79a69ca..626fefd 100644 --- a/src/Interfaces/ImportStatus.cs +++ b/src/Interfaces/ImportStatus.cs @@ -4,4 +4,4 @@ public class ImportStatus { public static string IsImporting = "IsImporting"; } -} \ No newline at end of file +} diff --git a/src/Interfaces/ImportUpdateCompletedData.cs b/src/Interfaces/ImportUpdateCompletedData.cs index badf92b..eb13b61 100644 --- a/src/Interfaces/ImportUpdateCompletedData.cs +++ b/src/Interfaces/ImportUpdateCompletedData.cs @@ -10,4 +10,4 @@ public class ImportUpdateCompletedData public bool ResourcesIncluded { get; set; } } -} \ No newline at end of file +} diff --git a/src/Interfaces/ImporterActions.cs b/src/Interfaces/ImporterActions.cs index 3172e74..c6ec141 100644 --- a/src/Interfaces/ImporterActions.cs +++ b/src/Interfaces/ImporterActions.cs @@ -3,8 +3,8 @@ public static class ImporterActions { public static string Added = "added"; - public static string Updated = "updated"; public static string Deleted = "deleted"; public static string Unlinked = "unlinked"; + public static string Updated = "updated"; } -} \ No newline at end of file +} diff --git a/src/Interfaces/InRiverImportResource.cs b/src/Interfaces/InRiverImportResource.cs index 73547d5..6d923e6 100644 --- a/src/Interfaces/InRiverImportResource.cs +++ b/src/Interfaces/InRiverImportResource.cs @@ -13,19 +13,19 @@ public InRiverImportResource() Codes = new List(); } - /// - /// The path to the exported resource file - /// - public string Path { get; set; } + public string Action { get; set; } - public List Codes { get; set; } + public List Codes { get; set; } public List EntryCodes { get; set; } - public string Action { get; set; } + public List MetaFields { get; set; } - public int ResourceId { get; set; } + /// + /// The path to the exported resource file + /// + public string Path { get; set; } - public List MetaFields { get; set; } + public int ResourceId { get; set; } } -} \ No newline at end of file +} diff --git a/src/Interfaces/Interfaces.csproj b/src/Interfaces/Interfaces.csproj index d765210..9ea1e90 100644 --- a/src/Interfaces/Interfaces.csproj +++ b/src/Interfaces/Interfaces.csproj @@ -72,13 +72,5 @@ - - \ No newline at end of file diff --git a/src/Interfaces/Poco/Data.cs b/src/Interfaces/Poco/Data.cs index 7f5416e..c3e8e2e 100644 --- a/src/Interfaces/Poco/Data.cs +++ b/src/Interfaces/Poco/Data.cs @@ -1,20 +1,20 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Xml.Serialization; namespace Epinova.InRiverConnector.Interfaces.Poco { - public class Data - { - [XmlAttribute("language")] - public string language { get; set; } - - [XmlAttribute("value")] - public string value { get; set; } - - [XmlText] - public string Value { get; set; } + public class Data + { + [XmlAttribute("language")] + public string language { get; set; } + + [XmlAttribute("value")] + public string value { get; set; } + + [XmlText] + public string Value { get; set; } [XmlElement("Item")] - public List Item { get; set; } - } + public List Item { get; set; } + } } diff --git a/src/Interfaces/Poco/EntryCode.cs b/src/Interfaces/Poco/EntryCode.cs index 86b5d84..729cd2a 100644 --- a/src/Interfaces/Poco/EntryCode.cs +++ b/src/Interfaces/Poco/EntryCode.cs @@ -2,26 +2,23 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - - public class EntryCode - { - // ATTRIBUTES - [XmlIgnore] - public bool IsMainPicture { get; set; } + public class EntryCode + { + public EntryCode() + { + } - [XmlAttribute("IsMainPicture")] - public string IsMainPictureString - { - get { return IsMainPicture ? "true" : "false"; } - set { IsMainPicture = value == "true"; } - } - - // ELEMENTS - [XmlText] - public string Value { get; set; } - - // CONSTRUCTOR - public EntryCode() - {} - } + [XmlIgnore] + public bool IsMainPicture { get; set; } + + [XmlAttribute("IsMainPicture")] + public string IsMainPictureString + { + get { return IsMainPicture ? "true" : "false"; } + set { IsMainPicture = value == "true"; } + } + + [XmlText] + public string Value { get; set; } + } } diff --git a/src/Interfaces/Poco/Item.cs b/src/Interfaces/Poco/Item.cs index 9d419db..acea2cd 100644 --- a/src/Interfaces/Poco/Item.cs +++ b/src/Interfaces/Poco/Item.cs @@ -2,15 +2,13 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - public class Item { - // ATTRIBUTES + public Item() + { + } + [XmlAttribute("value")] public string value { get; set; } - - // CONSTRUCTOR - public Item() - { } } } diff --git a/src/Interfaces/Poco/MetaField.cs b/src/Interfaces/Poco/MetaField.cs index a3fa52f..8921ea3 100644 --- a/src/Interfaces/Poco/MetaField.cs +++ b/src/Interfaces/Poco/MetaField.cs @@ -3,15 +3,15 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - public class MetaField - { - [XmlElement("Name")] - public Name Name { get; set; } - - [XmlElement("Type")] - public Type Type { get; set; } - - [XmlElement("Data")] - public List Data { get; set; } - } + public class MetaField + { + [XmlElement("Name")] + public Name Name { get; set; } + + [XmlElement("Type")] + public Type Type { get; set; } + + [XmlElement("Data")] + public List Data { get; set; } + } } diff --git a/src/Interfaces/Poco/Name.cs b/src/Interfaces/Poco/Name.cs index bc201b8..b00a239 100644 --- a/src/Interfaces/Poco/Name.cs +++ b/src/Interfaces/Poco/Name.cs @@ -2,10 +2,9 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - public class Name - { - // ELEMENTS - [XmlText] - public string Value { get; set; } - } + public class Name + { + [XmlText] + public string Value { get; set; } + } } diff --git a/src/Interfaces/Poco/ParentEntries.cs b/src/Interfaces/Poco/ParentEntries.cs index c67c4e0..b7803a4 100644 --- a/src/Interfaces/Poco/ParentEntries.cs +++ b/src/Interfaces/Poco/ParentEntries.cs @@ -3,9 +3,9 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - public class ParentEntries - { - [XmlElement("EntryCode")] - public List EntryCode { get; set; } - } + public class ParentEntries + { + [XmlElement("EntryCode")] + public List EntryCode { get; set; } + } } diff --git a/src/Interfaces/Poco/Path.cs b/src/Interfaces/Poco/Path.cs index bb86896..184253d 100644 --- a/src/Interfaces/Poco/Path.cs +++ b/src/Interfaces/Poco/Path.cs @@ -2,9 +2,9 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - public class Path - { - [XmlText] - public string Value { get; set; } - } + public class Path + { + [XmlText] + public string Value { get; set; } + } } diff --git a/src/Interfaces/Poco/Paths.cs b/src/Interfaces/Poco/Paths.cs index e51c17f..e79917a 100644 --- a/src/Interfaces/Poco/Paths.cs +++ b/src/Interfaces/Poco/Paths.cs @@ -2,9 +2,9 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - public class Paths - { - [XmlElement("Path")] - public Path Path { get; set; } - } -} \ No newline at end of file + public class Paths + { + [XmlElement("Path")] + public Path Path { get; set; } + } +} diff --git a/src/Interfaces/Poco/Resource.cs b/src/Interfaces/Poco/Resource.cs index 246d1d7..90582d6 100644 --- a/src/Interfaces/Poco/Resource.cs +++ b/src/Interfaces/Poco/Resource.cs @@ -1,22 +1,22 @@ -using System.Xml.Serialization; +using System.Xml.Serialization; namespace Epinova.InRiverConnector.Interfaces.Poco -{ - public class Resource - { - [XmlAttribute("id")] - public int id { get; set; } - - [XmlAttribute("action")] - public string action { get; set; } - - [XmlElement("ResourceFields")] - public ResourceFields ResourceFields { get; set; } - - [XmlElement("Paths")] - public Paths Paths { get; set; } - - [XmlElement("ParentEntries")] - public ParentEntries ParentEntries { get; set; } - } +{ + public class Resource + { + [XmlAttribute("id")] + public int id { get; set; } + + [XmlAttribute("action")] + public string action { get; set; } + + [XmlElement("ResourceFields")] + public ResourceFields ResourceFields { get; set; } + + [XmlElement("Paths")] + public Paths Paths { get; set; } + + [XmlElement("ParentEntries")] + public ParentEntries ParentEntries { get; set; } + } } diff --git a/src/Interfaces/Poco/ResourceFields.cs b/src/Interfaces/Poco/ResourceFields.cs index 64d3037..5f326ea 100644 --- a/src/Interfaces/Poco/ResourceFields.cs +++ b/src/Interfaces/Poco/ResourceFields.cs @@ -3,9 +3,9 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - public class ResourceFields - { - [XmlElement("MetaField")] - public List MetaField { get; set; } - } + public class ResourceFields + { + [XmlElement("MetaField")] + public List MetaField { get; set; } + } } diff --git a/src/Interfaces/Poco/ResourceFiles.cs b/src/Interfaces/Poco/ResourceFiles.cs index 484502d..4d9acb9 100644 --- a/src/Interfaces/Poco/ResourceFiles.cs +++ b/src/Interfaces/Poco/ResourceFiles.cs @@ -3,9 +3,9 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - public class ResourceFiles - { - [XmlElement("Resource")] - public List Resource { get; set; } - } + public class ResourceFiles + { + [XmlElement("Resource")] + public List Resource { get; set; } + } } diff --git a/src/Interfaces/Poco/ResourceMetaFields.cs b/src/Interfaces/Poco/ResourceMetaFields.cs index 1c0f0af..e42f43e 100644 --- a/src/Interfaces/Poco/ResourceMetaFields.cs +++ b/src/Interfaces/Poco/ResourceMetaFields.cs @@ -2,9 +2,9 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - public class ResourceMetaFields - { - [XmlText] - public string Value { get; set; } - } + public class ResourceMetaFields + { + [XmlText] + public string Value { get; set; } + } } diff --git a/src/Interfaces/Poco/Resources.cs b/src/Interfaces/Poco/Resources.cs index d157d50..a44cce9 100644 --- a/src/Interfaces/Poco/Resources.cs +++ b/src/Interfaces/Poco/Resources.cs @@ -2,12 +2,12 @@ namespace Epinova.InRiverConnector.Interfaces.Poco { - public class Resources - { - [XmlElement("ResourceMetaFields")] - public ResourceMetaFields ResourceMetaFields { get; set; } - - [XmlElement("ResourceFiles")] - public ResourceFiles ResourceFiles { get; set; } - } + public class Resources + { + [XmlElement("ResourceMetaFields")] + public ResourceMetaFields ResourceMetaFields { get; set; } + + [XmlElement("ResourceFiles")] + public ResourceFiles ResourceFiles { get; set; } + } } diff --git a/src/Interfaces/Poco/Type.cs b/src/Interfaces/Poco/Type.cs index 23e93e2..3378276 100644 --- a/src/Interfaces/Poco/Type.cs +++ b/src/Interfaces/Poco/Type.cs @@ -1,10 +1,10 @@ using System.Xml.Serialization; namespace Epinova.InRiverConnector.Interfaces.Poco -{ - public class Type - { - [XmlText] - public string Value { get; set; } - } +{ + public class Type + { + [XmlText] + public string Value { get; set; } + } } diff --git a/src/Interfaces/Properties/AssemblyInfo.cs b/src/Interfaces/Properties/AssemblyInfo.cs index c4a2bc7..8841f19 100644 --- a/src/Interfaces/Properties/AssemblyInfo.cs +++ b/src/Interfaces/Properties/AssemblyInfo.cs @@ -1,10 +1,6 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. [assembly: AssemblyTitle("Epinova.InRiverConnector.Interfaces")] [assembly: AssemblyDescription("")] [assembly: AssemblyCompany("")] @@ -12,19 +8,12 @@ [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("897a5e65-197c-4fba-b927-7adc3083bd64")] - -[assembly: AssemblyVersion("1.3.0.0")] -[assembly: AssemblyFileVersion("1.3.0.0")] +[assembly: AssemblyVersion("1.4.0.0")] +[assembly: AssemblyFileVersion("1.4.0.0")] #if DEBUG [assembly: AssemblyConfiguration("Debug")] #else [assembly: AssemblyConfiguration("Release")] -#endif \ No newline at end of file +#endif diff --git a/src/Interfaces/Value.cs b/src/Interfaces/Value.cs index 585069c..e934836 100644 --- a/src/Interfaces/Value.cs +++ b/src/Interfaces/Value.cs @@ -2,8 +2,7 @@ { public class Value { - public string Languagecode { get; set; } - public string Data { get; set; } + public string Languagecode { get; set; } } } diff --git a/tests/EpiserverAdapterTests/App.config b/tests/EpiserverAdapterTests/App.config index 2a5e54d..b676d36 100644 --- a/tests/EpiserverAdapterTests/App.config +++ b/tests/EpiserverAdapterTests/App.config @@ -1,6 +1,22 @@ - + - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/EpiserverAdapterTests/CatalogCodeGeneratorTests.cs b/tests/EpiserverAdapterTests/CatalogCodeGeneratorTests.cs index a1ed0e2..2ec9fa0 100644 --- a/tests/EpiserverAdapterTests/CatalogCodeGeneratorTests.cs +++ b/tests/EpiserverAdapterTests/CatalogCodeGeneratorTests.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Epinova.InRiverConnector.EpiserverAdapter; -using Epinova.InRiverConnector.EpiserverAdapter.Helpers; using inRiver.Remoting.Objects; using Moq; using Xunit; @@ -10,8 +9,8 @@ namespace Epinova.InRiverConnector.EpiserverAdapterTests public class CatalogCodeGeneratorTests { private readonly CatalogCodeGenerator _catalogCodeGenerator; - private Mock _config; - private Mock _entityService; + private readonly Mock _config; + private readonly Mock _entityService; public CatalogCodeGeneratorTests() { @@ -22,223 +21,223 @@ public CatalogCodeGeneratorTests() } [Fact] - public void GetEpiserverCodeWithEntityId_EntityIdIsZero_Null() - { - var episerverCode = _catalogCodeGenerator.GetEpiserverCode(0); - Assert.Null(episerverCode); - } - - [Fact] - public void GetEpiserverCodeWithEntity_NoMappingsExist_EntityId() + public void GetEpiserverCodeWithEntity_MappingsExist_NotValidForThisEntityType_ChannelPrefixExists_PrefixedEntityId() { - var id = 123; - var entity = EntityFactory.CreateItem(id); - - var result = _catalogCodeGenerator.GetEpiserverCode(entity); - Assert.Equal(id.ToString(), result); - } + string mappedField = "ProductOtherField"; - [Fact] - public void GetEpiserverCodeWithEntity_ValidMappingsExist_OtherFieldValue() - { - var mappedField = "ItemOtherField"; + var codeMapping = new Dictionary { { "Product", mappedField } }; + _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); - var codeMapping = new Dictionary - { - {"Item", mappedField} - }; + string channelPrefix = "Prefix_"; + _config.Setup(x => x.ChannelIdPrefix).Returns(channelPrefix); - _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); + int id = 123; + Entity entity = EntityFactory.CreateItem(id); + entity.Fields.Add(FieldFactory.CreateField("ABC", mappedField)); - var id = 123; - var expectedCode = "ABC"; - var entity = EntityFactory.CreateItem(id); - entity.Fields.Add(FieldFactory.CreateField(expectedCode, mappedField)); - - var result = _catalogCodeGenerator.GetEpiserverCode(entity); - Assert.Equal(expectedCode, result); + string result = _catalogCodeGenerator.GetEpiserverCode(entity); + Assert.Equal($"{channelPrefix}{id}", result); } [Fact] public void GetEpiserverCodeWithEntity_MappingsExist_NotValidForThisEntityType_EntityId() { - var mappedField = "ProductOtherField"; + string mappedField = "ProductOtherField"; var codeMapping = new Dictionary { - {"Product", mappedField} + { "Product", mappedField } }; _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); - var id = 123; - var entity = EntityFactory.CreateItem(id); + int id = 123; + Entity entity = EntityFactory.CreateItem(id); entity.Fields.Add(FieldFactory.CreateField("ABC", mappedField)); - var result = _catalogCodeGenerator.GetEpiserverCode(entity); + string result = _catalogCodeGenerator.GetEpiserverCode(entity); Assert.Equal(id.ToString(), result); } [Fact] - public void GetEpiserverCodeWithEntity_MappingsExist_NotValidForThisEntityType_ChannelPrefixExists_PrefixedEntityId() + public void GetEpiserverCodeWithEntity_NoMappingsExist_ChannelPrefixExists_PrefixedEntityId() { - var mappedField = "ProductOtherField"; + int id = 123; + Entity entity = EntityFactory.CreateItem(id); - var codeMapping = new Dictionary { {"Product", mappedField} }; - _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); - - var channelPrefix = "Prefix_"; + string channelPrefix = "Prefix_"; _config.Setup(x => x.ChannelIdPrefix).Returns(channelPrefix); - var id = 123; - var entity = EntityFactory.CreateItem(id); - entity.Fields.Add(FieldFactory.CreateField("ABC", mappedField)); - - var result = _catalogCodeGenerator.GetEpiserverCode(entity); + string result = _catalogCodeGenerator.GetEpiserverCode(entity); Assert.Equal($"{channelPrefix}{id}", result); } [Fact] - public void GetEpiserverCodeWithEntity_NoMappingsExist_ChannelPrefixExists_PrefixedEntityId() + public void GetEpiserverCodeWithEntity_NoMappingsExist_EntityId() { - var id = 123; - var entity = EntityFactory.CreateItem(id); - - var channelPrefix = "Prefix_"; - _config.Setup(x => x.ChannelIdPrefix).Returns(channelPrefix); + int id = 123; + Entity entity = EntityFactory.CreateItem(id); - var result = _catalogCodeGenerator.GetEpiserverCode(entity); - Assert.Equal($"{channelPrefix}{id}", result); + string result = _catalogCodeGenerator.GetEpiserverCode(entity); + Assert.Equal(id.ToString(), result); } [Fact] public void GetEpiserverCodeWithEntity_ValidMappingsExist_ChannelPrefixExists_PrefixedOtherFieldValue() { - var mappedField = "ItemOtherField"; + string mappedField = "ItemOtherField"; - var codeMapping = new Dictionary { {"Item", mappedField} }; + var codeMapping = new Dictionary { { "Item", mappedField } }; _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); - var channelPrefix = "Prefix_"; + string channelPrefix = "Prefix_"; _config.Setup(x => x.ChannelIdPrefix).Returns(channelPrefix); - var id = 123; - var expectedCode = "ABC"; - var entity = EntityFactory.CreateItem(id); + int id = 123; + string expectedCode = "ABC"; + Entity entity = EntityFactory.CreateItem(id); entity.Fields.Add(FieldFactory.CreateField(expectedCode, mappedField)); - var result = _catalogCodeGenerator.GetEpiserverCode(entity); + string result = _catalogCodeGenerator.GetEpiserverCode(entity); Assert.Equal($"{channelPrefix}{expectedCode}", result); } [Fact] - public void GetEpiserverCodeWithEntityId_NoMappingsExist_EntityId() + public void GetEpiserverCodeWithEntity_ValidMappingsExist_OtherFieldValue() { - var id = 123; - var entity = EntityFactory.CreateItem(id); + string mappedField = "ItemOtherField"; - _entityService.Setup(x => x.GetEntity(It.IsAny(), It.IsAny())).Returns(entity); + var codeMapping = new Dictionary + { + { "Item", mappedField } + }; - var result = _catalogCodeGenerator.GetEpiserverCode(id); - Assert.Equal(id.ToString(), result); + _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); + + int id = 123; + string expectedCode = "ABC"; + Entity entity = EntityFactory.CreateItem(id); + entity.Fields.Add(FieldFactory.CreateField(expectedCode, mappedField)); + + string result = _catalogCodeGenerator.GetEpiserverCode(entity); + Assert.Equal(expectedCode, result); } [Fact] - public void GetEpiserverCodeWithEntityId_ValidMappingsExist_OtherFieldValue() + public void GetEpiserverCodeWithEntityId_EntityIdIsZero_Null() { - var mappedField = "ItemOtherField"; + string episerverCode = _catalogCodeGenerator.GetEpiserverCode(0); + Assert.Null(episerverCode); + } - var codeMapping = new Dictionary - { - {"Item", mappedField} - }; + [Fact] + public void GetEpiserverCodeWithEntityId_MappingsExist_NotValidForThisEntityType_ChannelPrefixExists_PrefixedEntityId() + { + string mappedField = "ProductOtherField"; + var codeMapping = new Dictionary { { "Product", mappedField } }; _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); - var id = 123; - var expectedCode = "ABC"; - var entity = EntityFactory.CreateItem(id); - entity.Fields.Add(FieldFactory.CreateField(expectedCode, mappedField)); + string channelPrefix = "Prefix_"; + _config.Setup(x => x.ChannelIdPrefix).Returns(channelPrefix); + + int id = 123; + Entity entity = EntityFactory.CreateItem(id); + entity.Fields.Add(FieldFactory.CreateField("ABC", mappedField)); _entityService.Setup(x => x.GetEntity(It.IsAny(), It.IsAny())).Returns(entity); - var result = _catalogCodeGenerator.GetEpiserverCode(id); - Assert.Equal(expectedCode, result); + string result = _catalogCodeGenerator.GetEpiserverCode(id); + Assert.Equal($"{channelPrefix}{id}", result); } [Fact] public void GetEpiserverCodeWithEntityId_MappingsExist_NotValidForThisEntityType_EntityId() { - var mappedField = "ProductOtherField"; + string mappedField = "ProductOtherField"; var codeMapping = new Dictionary { - {"Product", mappedField} + { "Product", mappedField } }; _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); - var id = 123; - var entity = EntityFactory.CreateItem(id); + int id = 123; + Entity entity = EntityFactory.CreateItem(id); entity.Fields.Add(FieldFactory.CreateField("ABC", mappedField)); - + _entityService.Setup(x => x.GetEntity(It.IsAny(), It.IsAny())).Returns(entity); - var result = _catalogCodeGenerator.GetEpiserverCode(id); + string result = _catalogCodeGenerator.GetEpiserverCode(id); Assert.Equal(id.ToString(), result); } [Fact] - public void GetEpiserverCodeWithEntityId_MappingsExist_NotValidForThisEntityType_ChannelPrefixExists_PrefixedEntityId() + public void GetEpiserverCodeWithEntityId_NoMappingsExist_ChannelPrefixExists_PrefixedEntityId() { - var mappedField = "ProductOtherField"; - - var codeMapping = new Dictionary { { "Product", mappedField } }; - _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); + int id = 123; + Entity entity = EntityFactory.CreateItem(id); - var channelPrefix = "Prefix_"; + string channelPrefix = "Prefix_"; _config.Setup(x => x.ChannelIdPrefix).Returns(channelPrefix); - - var id = 123; - var entity = EntityFactory.CreateItem(id); - entity.Fields.Add(FieldFactory.CreateField("ABC", mappedField)); - _entityService.Setup(x => x.GetEntity(It.IsAny(), It.IsAny())).Returns(entity); - var result = _catalogCodeGenerator.GetEpiserverCode(id); + + string result = _catalogCodeGenerator.GetEpiserverCode(id); Assert.Equal($"{channelPrefix}{id}", result); } [Fact] - public void GetEpiserverCodeWithEntityId_NoMappingsExist_ChannelPrefixExists_PrefixedEntityId() + public void GetEpiserverCodeWithEntityId_NoMappingsExist_EntityId() { - var id = 123; - var entity = EntityFactory.CreateItem(id); + int id = 123; + Entity entity = EntityFactory.CreateItem(id); - var channelPrefix = "Prefix_"; - _config.Setup(x => x.ChannelIdPrefix).Returns(channelPrefix); _entityService.Setup(x => x.GetEntity(It.IsAny(), It.IsAny())).Returns(entity); - var result = _catalogCodeGenerator.GetEpiserverCode(id); - Assert.Equal($"{channelPrefix}{id}", result); + string result = _catalogCodeGenerator.GetEpiserverCode(id); + Assert.Equal(id.ToString(), result); } [Fact] public void GetEpiserverCodeWithEntityId_ValidMappingsExist_ChannelPrefixExists_PrefixedOtherFieldValue() { - var mappedField = "ItemOtherField"; + string mappedField = "ItemOtherField"; var codeMapping = new Dictionary { { "Item", mappedField } }; _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); - var channelPrefix = "Prefix_"; + string channelPrefix = "Prefix_"; _config.Setup(x => x.ChannelIdPrefix).Returns(channelPrefix); - var id = 123; - var expectedCode = "ABC"; - var entity = EntityFactory.CreateItem(id); + int id = 123; + string expectedCode = "ABC"; + Entity entity = EntityFactory.CreateItem(id); entity.Fields.Add(FieldFactory.CreateField(expectedCode, mappedField)); - + _entityService.Setup(x => x.GetEntity(It.IsAny(), It.IsAny())).Returns(entity); - var result = _catalogCodeGenerator.GetEpiserverCode(id); + string result = _catalogCodeGenerator.GetEpiserverCode(id); Assert.Equal($"{channelPrefix}{expectedCode}", result); } + + [Fact] + public void GetEpiserverCodeWithEntityId_ValidMappingsExist_OtherFieldValue() + { + string mappedField = "ItemOtherField"; + + var codeMapping = new Dictionary + { + { "Item", mappedField } + }; + + _config.Setup(x => x.EpiCodeMapping).Returns(codeMapping); + + int id = 123; + string expectedCode = "ABC"; + Entity entity = EntityFactory.CreateItem(id); + entity.Fields.Add(FieldFactory.CreateField(expectedCode, mappedField)); + + _entityService.Setup(x => x.GetEntity(It.IsAny(), It.IsAny())).Returns(entity); + string result = _catalogCodeGenerator.GetEpiserverCode(id); + Assert.Equal(expectedCode, result); + } } -} \ No newline at end of file +} diff --git a/tests/EpiserverAdapterTests/CatalogElementFactoryTests.cs b/tests/EpiserverAdapterTests/CatalogElementFactoryTests.cs index 079a409..4b1a2af 100644 --- a/tests/EpiserverAdapterTests/CatalogElementFactoryTests.cs +++ b/tests/EpiserverAdapterTests/CatalogElementFactoryTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Xml.Linq; using Epinova.InRiverConnector.EpiserverAdapter; using Epinova.InRiverConnector.EpiserverAdapter.Helpers; using Epinova.InRiverConnector.EpiserverAdapter.XmlFactories; @@ -14,25 +15,19 @@ namespace Epinova.InRiverConnector.EpiserverAdapterTests { public class CatalogElementFactoryTests { - private readonly FakeCatalogCodeGenerator _catalogCodeGenerator; private readonly CatalogElementFactory _catalogElementFactory; - private readonly Mock _configMock; - private readonly FakeEpiMappingHelper _mappingHelper; private readonly Mock _pimFieldAdapterMock; public CatalogElementFactoryTests() { - _configMock = new Mock(); - _mappingHelper = new FakeEpiMappingHelper(); - _catalogCodeGenerator = new FakeCatalogCodeGenerator(); + var configMock = new Mock(); + var mappingHelper = new FakeEpiMappingHelper(); + var catalogCodeGenerator = new FakeCatalogCodeGenerator(); _pimFieldAdapterMock = new Mock(); - _catalogElementFactory = new CatalogElementFactory(_configMock.Object, - _mappingHelper, _catalogCodeGenerator, - _pimFieldAdapterMock.Object); + _catalogElementFactory = new CatalogElementFactory(configMock.Object, mappingHelper, catalogCodeGenerator, _pimFieldAdapterMock.Object); - _configMock.Setup(m => m.LanguageMapping).Returns(new Dictionary - {{CultureInfo.CurrentCulture, CultureInfo.CurrentCulture}}); + configMock.Setup(m => m.LanguageMapping).Returns(new Dictionary { { CultureInfo.CurrentCulture, CultureInfo.CurrentCulture } }); } [Theory] @@ -49,11 +44,11 @@ public void SeoFieldValueIsEmpty_CreateSEOInfoElement_DoesNotReturnEmptyNode(str _pimFieldAdapterMock .Setup(m => m.GetFieldValue(It.IsAny(), It.Is(s => !s.Equals(name)), It.IsAny())) - .Returns(string.Empty); + .Returns(String.Empty); - var result = _catalogElementFactory.CreateSEOInfoElement(EntityFactory.CreateItem(123)); + XElement result = _catalogElementFactory.CreateSeoInfoElement(EntityFactory.CreateItem(123)); Assert.Equal(3, result.Descendants().Count()); } } -} \ No newline at end of file +} diff --git a/tests/EpiserverAdapterTests/EntityFactory.cs b/tests/EpiserverAdapterTests/EntityFactory.cs index ab0727b..10c5375 100644 --- a/tests/EpiserverAdapterTests/EntityFactory.cs +++ b/tests/EpiserverAdapterTests/EntityFactory.cs @@ -16,4 +16,4 @@ public static Entity CreateItem(int id) }; } } -} \ No newline at end of file +} diff --git a/tests/EpiserverAdapterTests/EpiserverAdapterTests.csproj b/tests/EpiserverAdapterTests/EpiserverAdapterTests.csproj index 2205056..786b40b 100644 --- a/tests/EpiserverAdapterTests/EpiserverAdapterTests.csproj +++ b/tests/EpiserverAdapterTests/EpiserverAdapterTests.csproj @@ -1,6 +1,6 @@  - + Debug @@ -12,9 +12,9 @@ v4.6.1 512 true - - + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + UnitTest AnyCPU @@ -42,15 +42,34 @@ ..\..\packages\Castle.Core.4.2.1\lib\net45\Castle.Core.dll + + False + ..\..\lib\inRiver.Integration.exe + ..\..\lib\inRiver.Remoting.dll - - ..\..\packages\Moq.4.7.145\lib\net45\Moq.dll + + ..\..\packages\Moq.4.8.2\lib\net45\Moq.dll + + + ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + + + ..\..\packages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + + ..\..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + + + ..\..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll + @@ -58,16 +77,16 @@ - ..\..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll + ..\..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll - - ..\..\packages\xunit.assert.2.3.1\lib\netstandard1.1\xunit.assert.dll + + ..\..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll - - ..\..\packages\xunit.extensibility.core.2.3.1\lib\netstandard1.1\xunit.core.dll + + ..\..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll - - ..\..\packages\xunit.extensibility.execution.2.3.1\lib\net452\xunit.execution.desktop.dll + + ..\..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll @@ -92,15 +111,8 @@ - + - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - + \ No newline at end of file diff --git a/tests/EpiserverAdapterTests/Fakes/FakeCatalogCodeGenerator.cs b/tests/EpiserverAdapterTests/Fakes/FakeCatalogCodeGenerator.cs index 801299d..a336783 100644 --- a/tests/EpiserverAdapterTests/Fakes/FakeCatalogCodeGenerator.cs +++ b/tests/EpiserverAdapterTests/Fakes/FakeCatalogCodeGenerator.cs @@ -7,7 +7,6 @@ public class FakeCatalogCodeGenerator : CatalogCodeGenerator { public FakeCatalogCodeGenerator() : base(new Mock().Object, new Mock().Object) { - } } -} \ No newline at end of file +} diff --git a/tests/EpiserverAdapterTests/Fakes/FakeEpiMappingHelper.cs b/tests/EpiserverAdapterTests/Fakes/FakeEpiMappingHelper.cs index 1df3828..6a5db98 100644 --- a/tests/EpiserverAdapterTests/Fakes/FakeEpiMappingHelper.cs +++ b/tests/EpiserverAdapterTests/Fakes/FakeEpiMappingHelper.cs @@ -10,4 +10,4 @@ public class FakeEpiMappingHelper : EpiMappingHelper { } } -} \ No newline at end of file +} diff --git a/tests/EpiserverAdapterTests/Fakes/FakePimFieldAdapter.cs b/tests/EpiserverAdapterTests/Fakes/FakePimFieldAdapter.cs index 4eb0fd7..4413d66 100644 --- a/tests/EpiserverAdapterTests/Fakes/FakePimFieldAdapter.cs +++ b/tests/EpiserverAdapterTests/Fakes/FakePimFieldAdapter.cs @@ -10,4 +10,4 @@ public FakePimFieldAdapter() : base(new Mock().Object) { } } -} \ No newline at end of file +} diff --git a/tests/EpiserverAdapterTests/FieldFactory.cs b/tests/EpiserverAdapterTests/FieldFactory.cs index 4d39d32..be3c3b3 100644 --- a/tests/EpiserverAdapterTests/FieldFactory.cs +++ b/tests/EpiserverAdapterTests/FieldFactory.cs @@ -8,9 +8,9 @@ public static Field CreateField(object value, string typeId) { return new Field { - FieldType = new FieldType {Id = typeId}, + FieldType = new FieldType { Id = typeId }, Data = value }; } } -} \ No newline at end of file +} diff --git a/tests/EpiserverAdapterTests/Helpers/EpiMappingHelperTests.cs b/tests/EpiserverAdapterTests/Helpers/EpiMappingHelperTests.cs index 93678b3..a82f723 100644 --- a/tests/EpiserverAdapterTests/Helpers/EpiMappingHelperTests.cs +++ b/tests/EpiserverAdapterTests/Helpers/EpiMappingHelperTests.cs @@ -9,60 +9,59 @@ namespace Epinova.InRiverConnector.EpiserverAdapterTests.Helpers { public class EpiMappingHelperTests { - Mock _config; - EpiMappingHelper _epiMappingHelper; - Mock _pimFieldAdapter; + private readonly Mock _config; + private readonly EpiMappingHelper _epiMappingHelper; public EpiMappingHelperTests() { _config = new Mock(); - _pimFieldAdapter = new Mock(); - _epiMappingHelper = new EpiMappingHelper(_config.Object, _pimFieldAdapter.Object); + var pimFieldAdapter = new Mock(); + _epiMappingHelper = new EpiMappingHelper(_config.Object, pimFieldAdapter.Object); } [Fact] public void IsChannelNodeLink_SourceTypeIsChannelNode_True() { - var linkTypeId = "ChannelNodeProduct"; + string linkTypeId = "ChannelNodeProduct"; var linkTypes = new List { - new LinkType {Id = linkTypeId, SourceEntityTypeId = "ChannelNode"} + new LinkType { Id = linkTypeId, SourceEntityTypeId = "ChannelNode" } }; _config.Setup(x => x.LinkTypes).Returns(linkTypes); - var result = _epiMappingHelper.IsChannelNodeLink(linkTypeId); + bool result = _epiMappingHelper.IsChannelNodeLink(linkTypeId); Assert.True(result); } [Fact] public void IsChannelNodeLink_SourceTypeIsChannelTargetIsChannelNode_True() { - var linkTypeId = "ChannelNodeProduct"; + string linkTypeId = "ChannelNodeProduct"; var linkTypes = new List { - new LinkType {Id = linkTypeId, SourceEntityTypeId = "Channel", TargetEntityTypeId = "ChannelNode"} + new LinkType { Id = linkTypeId, SourceEntityTypeId = "Channel", TargetEntityTypeId = "ChannelNode" } }; _config.Setup(x => x.LinkTypes).Returns(linkTypes); - var result = _epiMappingHelper.IsChannelNodeLink(linkTypeId); + bool result = _epiMappingHelper.IsChannelNodeLink(linkTypeId); Assert.True(result); } [Fact] public void IsChannelNodeLink_SourceTypeIsNotChannelNode_False() { - var linkTypeId = "ProductItems"; + string linkTypeId = "ProductItems"; var linkTypes = new List { - new LinkType {Id = linkTypeId, SourceEntityTypeId = "Product"} + new LinkType { Id = linkTypeId, SourceEntityTypeId = "Product" } }; _config.Setup(x => x.LinkTypes).Returns(linkTypes); - var result = _epiMappingHelper.IsChannelNodeLink(linkTypeId); + bool result = _epiMappingHelper.IsChannelNodeLink(linkTypeId); Assert.False(result); } } -} \ No newline at end of file +} diff --git a/tests/EpiserverAdapterTests/Properties/AssemblyInfo.cs b/tests/EpiserverAdapterTests/Properties/AssemblyInfo.cs index 13403f6..c474ccd 100644 --- a/tests/EpiserverAdapterTests/Properties/AssemblyInfo.cs +++ b/tests/EpiserverAdapterTests/Properties/AssemblyInfo.cs @@ -1,10 +1,6 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. [assembly: AssemblyTitle("EpiserverAdapterTests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] @@ -13,24 +9,7 @@ [assembly: AssemblyCopyright("Copyright © 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("9cbb23af-fc5f-45ca-81be-47365dfde0b8")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.3.0.0")] -[assembly: AssemblyFileVersion("1.3.0.0")] +[assembly: AssemblyVersion("1.4.0.0")] +[assembly: AssemblyFileVersion("1.4.0.0")] diff --git a/tests/EpiserverAdapterTests/packages.config b/tests/EpiserverAdapterTests/packages.config index 2b5297a..1b1d094 100644 --- a/tests/EpiserverAdapterTests/packages.config +++ b/tests/EpiserverAdapterTests/packages.config @@ -1,12 +1,17 @@  - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file