Skip to content

Commit

Permalink
Merge pull request #8 from umbraco/feature/shopify-v9-multi-target
Browse files Browse the repository at this point in the history
Shopify Property Editor multi-targeted & V9 test site
  • Loading branch information
acoumb authored Mar 2, 2022
2 parents 49e6ba2 + b2acb10 commit 354ebb1
Show file tree
Hide file tree
Showing 33 changed files with 980 additions and 263 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Collections.Specialized;

namespace Umbraco.Cms.Integrations.Commerce.Shopify.Configuration
{
public class ShopifySettings
{
public ShopifySettings()
{

}

public ShopifySettings(NameValueCollection appSettings)
{
ApiVersion = appSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyApiVersion];
Shop = appSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyShop];
AccessToken = appSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyAccessToken];
}

public string ApiVersion { get; set; }

public string Shop { get; set; }

public string AccessToken { get; set; }
}
}
5 changes: 5 additions & 0 deletions src/Umbraco.Cms.Integrations.Commerce.Shopify/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ public static class Constants

public const string AppPluginFolderPath = "~/App_Plugins/UmbracoCms.Integrations/Commerce/Shopify";

public static class Configuration
{
public const string Settings = "Umbraco:Cms:Integrations:Commerce:Shopify:Settings";
}

public static class PropertyEditors
{
public const string ProductPickerAlias = "Umbraco.Cms.Integrations.Commerce.Shopify.ProductPicker";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using Newtonsoft.Json;
using System.Threading.Tasks;

using Umbraco.Cms.Integrations.Commerce.Shopify.Models.Dtos;
using Umbraco.Cms.Integrations.Shared.Models;
using Umbraco.Web.Mvc;
using Umbraco.Cms.Integrations.Shared.Models.Dtos;
using Umbraco.Cms.Integrations.Shared.Services;


#if NETCOREAPP
using Microsoft.AspNetCore.Mvc;

using Umbraco.Cms.Web.BackOffice.Controllers;
using Umbraco.Cms.Web.Common.Attributes;
#else
using System.Web.Http;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
#endif

namespace Umbraco.Cms.Integrations.Commerce.Shopify.Controllers
{
Expand All @@ -16,13 +24,9 @@ public class ProductsController : UmbracoAuthorizedApiController
{
private readonly IApiService<ProductsListDto> _apiService;

private readonly ICacheHelper _cacheHelper;

public ProductsController(IApiService<ProductsListDto> apiService, ICacheHelper cacheHelper)
public ProductsController(IApiService<ProductsListDto> apiService)
{
_apiService = apiService;

_cacheHelper = cacheHelper;
}

[HttpGet]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
using Umbraco.Cms.Integrations.Commerce.Shopify.Models;
using Umbraco.Cms.Integrations.Shared.Models;

#if NETCOREAPP
using Umbraco.Cms.Core.PropertyEditors;
#else
using Umbraco.Core.PropertyEditors;
#endif

namespace Umbraco.Cms.Integrations.Commerce.Shopify.Editors
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
using Umbraco.Core.PropertyEditors;
#if NETCOREAPP
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.PropertyEditors;
#else
using Umbraco.Core.PropertyEditors;
#endif

namespace Umbraco.Cms.Integrations.Commerce.Shopify.Editors
{
public class ShopifyProductPickerConfigurationEditor: ConfigurationEditor<ShopifyProductPickerConfiguration>
{
#if NETCOREAPP
public ShopifyProductPickerConfigurationEditor(IIOHelper ioHelper) : base(ioHelper)
{
}
#endif
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
using Umbraco.Core.Logging;
#if NETCOREAPP
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.PropertyEditors;
#else
using Umbraco.Core.Logging;
using Umbraco.Core.PropertyEditors;
#endif

namespace Umbraco.Cms.Integrations.Commerce.Shopify.Editors
{
Expand All @@ -11,6 +16,19 @@ namespace Umbraco.Cms.Integrations.Commerce.Shopify.Editors
Icon = "icon-shopping-basket-alt")]
public class ShopifyProductPickerPropertyEditor: DataEditor
{
#if NETCOREAPP
private IIOHelper _ioHelper;

public ShopifyProductPickerPropertyEditor(IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper) : base(dataValueEditorFactory)
{
_ioHelper = ioHelper;
}

protected override IConfigurationEditor CreateConfigurationEditor()
{
return new ShopifyProductPickerConfigurationEditor(_ioHelper);
}
#else
public ShopifyProductPickerPropertyEditor(ILogger logger) : base(logger)
{
}
Expand All @@ -19,5 +37,6 @@ protected override IConfigurationEditor CreateConfigurationEditor()
{
return new ShopifyProductPickerConfigurationEditor();
}
#endif
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Umbraco.Cms.Integrations.Commerce.Shopify.Models.Dtos;
using Umbraco.Cms.Integrations.Commerce.Shopify.Models.ViewModels;
using Umbraco.Cms.Integrations.Shared.Services;

#if NETCOREAPP
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Models.PublishedContent;
#else
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors;
#endif

namespace Umbraco.Cms.Integrations.Commerce.Shopify.Editors
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
using System.Collections.Generic;

#if NETCOREAPP
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
#else
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
#endif

using Umbraco.Cms.Integrations.Commerce.Shopify.Models.ViewModels;

namespace Umbraco.Cms.Integrations.Commerce.Shopify.Helpers
{
public static class ShopifyHtmlExtensions
{
public static IHtmlString RenderProductsList(this HtmlHelper htmlHelper, List<ProductViewModel> vm)
#if NETCOREAPP
public static IHtmlContent RenderShopifyProductsList(this HtmlHelper htmlHelper, List<ProductViewModel> vm)
{
return htmlHelper.Partial($"{Constants.AppPluginFolderPath}/Render/Products.cshtml", vm);
}
#else
public static IHtmlString RenderShopifyProductsList(this HtmlHelper htmlHelper, List<ProductViewModel> vm)
{
return htmlHelper.Partial($"{Constants.AppPluginFolderPath}/Render/Products.cshtml", vm);
}
#endif
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

namespace Umbraco.Cms.Integrations.Commerce.Shopify.Resources
{
public class LoggingResources
{
public const string AccessTokenMissing = "Cannot access Shopify - Access Token is missing.";

public const string FetchProductsFailed =
"Failed to fetch products from Shopify store using access token: {0}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,33 @@
using System.Threading.Tasks;

using Newtonsoft.Json;

using Umbraco.Cms.Integrations.Commerce.Shopify.Configuration;
using Umbraco.Cms.Integrations.Commerce.Shopify.Models.Dtos;
using Umbraco.Cms.Integrations.Shared.Configuration;
using Umbraco.Cms.Integrations.Shared.Models;
using Umbraco.Cms.Integrations.Shared.Models.Dtos;
using Umbraco.Cms.Integrations.Shared.Resolvers;
using Umbraco.Cms.Integrations.Shared.Services;
using Umbraco.Cms.Integrations.Commerce.Shopify.Resources;

#if NETCOREAPP
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

#else
using System.Configuration;
using Umbraco.Core.Logging;
#endif

namespace Umbraco.Cms.Integrations.Commerce.Shopify.Services
{
public class ShopifyService: BaseService, IApiService<ProductsListDto>
{
private readonly JsonSerializerSettings _serializerSettings;

public ShopifyService(ILogger logger, IAppSettings appSettings, ITokenService tokenService): base(logger, appSettings, tokenService)
private ShopifySettings Options;

#if NETCOREAPP
public ShopifyService(ILogger<ShopifyService> logger, IOptions<ShopifySettings> options, ITokenService tokenService) : base(logger, tokenService)
{
var resolver = new JsonPropertyRenameContractResolver();
resolver.RenameProperty(typeof(ResponseDto<ProductsListDto>), "Result", "products");
Expand All @@ -29,16 +40,32 @@ public ShopifyService(ILogger logger, IAppSettings appSettings, ITokenService to
{
ContractResolver = resolver
};

Options = options.Value;
}
#else
public ShopifyService(ILogger logger, ITokenService tokenService): base(logger, tokenService)
{
var resolver = new JsonPropertyRenameContractResolver();
resolver.RenameProperty(typeof(ResponseDto<ProductsListDto>), "Result", "products");

_serializerSettings = new JsonSerializerSettings
{
ContractResolver = resolver
};

Options = new ShopifySettings(ConfigurationManager.AppSettings);
}
#endif

public EditorSettings GetApiConfiguration()
{
if (string.IsNullOrEmpty(AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyShop])
|| string.IsNullOrEmpty(AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyApiVersion]))
if (string.IsNullOrEmpty(Options.Shop)
|| string.IsNullOrEmpty(Options.ApiVersion))
return new EditorSettings();

return
!string.IsNullOrEmpty(AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyAccessToken])
!string.IsNullOrEmpty(Options.AccessToken)
? new EditorSettings { IsValid = true, Type = ConfigurationType.Api }
: !string.IsNullOrEmpty(SettingsService.OAuthClientId)
&& !string.IsNullOrEmpty(OAuthProxyBaseUrl)
Expand All @@ -51,7 +78,7 @@ public string GetAuthorizationUrl()
{
return
string.Format(SettingsService.AuthorizationUrl,
AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyShop], SettingsService.OAuthClientId, SettingsService.ShopifyOAuthProxyUrl);
Options.Shop, SettingsService.OAuthClientId, SettingsService.ShopifyOAuthProxyUrl);
}

public async Task<string> GetAccessToken(OAuthRequestDto request)
Expand All @@ -70,8 +97,7 @@ public async Task<string> GetAccessToken(OAuthRequestDto request)
Content = new FormUrlEncodedContent(data)
};
requestMessage.Headers.Add("service_name", SettingsService.ServiceName);
requestMessage.Headers.Add(SettingsService.ServiceAddressReplace,
AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyShop]);
requestMessage.Headers.Add(SettingsService.ServiceAddressReplace, Options.Shop);

var response = await ClientFactory().SendAsync(requestMessage);
if (response.IsSuccessStatusCode)
Expand Down Expand Up @@ -102,7 +128,11 @@ public async Task<ResponseDto<ProductsListDto>> ValidateAccessToken()

if (string.IsNullOrEmpty(accessToken))
{
UmbCoreLogger.Info<ShopifyService>(message: "Cannot access Shopify - Access Token is missing.");
#if NETCOREAPP
UmbCoreLogger.LogInformation(LoggingResources.AccessTokenMissing);
#else
UmbCoreLogger.Info<ShopifyService>(message: LoggingResources.AccessTokenMissing);
#endif

return new ResponseDto<ProductsListDto>();
}
Expand All @@ -111,8 +141,8 @@ public async Task<ResponseDto<ProductsListDto>> ValidateAccessToken()
{
Method = HttpMethod.Get,
RequestUri = new Uri(string.Format(SettingsService.ProductsApiEndpoint,
AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyShop],
AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyApiVersion]))
Options.Shop,
Options.ApiVersion))
};
requestMessage.Headers.Add("X-Shopify-Access-Token", accessToken);

Expand All @@ -137,12 +167,16 @@ public async Task<ResponseDto<ProductsListDto>> GetResults()
TokenService.TryGetParameters(SettingsService.AccessTokenDbKey, out accessToken);
else
{
accessToken = AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyAccessToken];
accessToken = Options.AccessToken;
}

if (string.IsNullOrEmpty(accessToken))
{
UmbCoreLogger.Info<ShopifyService>(message: "Cannot access Shopify - Access Token is missing.");
#if NETCOREAPP
UmbCoreLogger.LogInformation(LoggingResources.AccessTokenMissing);
#else
UmbCoreLogger.Info<ShopifyService>(message: LoggingResources.AccessTokenMissing);
#endif

return new ResponseDto<ProductsListDto>();
}
Expand All @@ -151,15 +185,19 @@ public async Task<ResponseDto<ProductsListDto>> GetResults()
{
Method = HttpMethod.Get,
RequestUri = new Uri(string.Format(SettingsService.ProductsApiEndpoint,
AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyShop],
AppSettings[Constants.UmbracoCmsIntegrationsCommerceShopifyApiVersion]))
Options.Shop,
Options.ApiVersion))
};
requestMessage.Headers.Add("X-Shopify-Access-Token", accessToken);

var response = await ClientFactory().SendAsync(requestMessage);
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
UmbCoreLogger.Error<ShopifyService>($"Failed to fetch products from Shopify store using access token: {response.ReasonPhrase}");
#if NETCOREAPP
UmbCoreLogger.LogError(string.Format(LoggingResources.FetchProductsFailed, response.ReasonPhrase));
#else
UmbCoreLogger.Error<ShopifyService>(string.Format(LoggingResources.FetchProductsFailed, response.ReasonPhrase));
#endif

return new ResponseDto<ProductsListDto> { Message = response.ReasonPhrase };
}
Expand Down
Loading

0 comments on commit 354ebb1

Please sign in to comment.