Merge pull request #88 from leekelleher/feature/pkgrepo-restapi
Package Repo REST API
This commit is contained in:
@@ -19,7 +19,7 @@ namespace OurUmbraco.MarketPlace.Providers
|
||||
{
|
||||
var karmaList = new List<IKarma>();
|
||||
|
||||
using (var reader = Data.SqlHelper.ExecuteReader("SELECT id as ProjectId, SUM(points) Points FROM powersProject GROUP BY id"))
|
||||
using (var reader = Data.SqlHelper.ExecuteReader("SELECT id as ProjectId, SUM(points) Points FROM powersProject GROUP BY id ORDER BY SUM(points) DESC"))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
|
||||
+19
-8
@@ -214,13 +214,17 @@ namespace OurUmbraco.Our
|
||||
Data.SqlHelper.CreateParameter("@memberId", memberId)) > 0));
|
||||
}
|
||||
|
||||
public static string GetMemberAvatar(IPublishedContent member, int avatarSize)
|
||||
public static string GetMemberAvatar(IPublishedContent member, int avatarSize, bool getRawUrl = false)
|
||||
{
|
||||
var memberAvatarPath = MemberAvatarPath(member);
|
||||
if (string.IsNullOrWhiteSpace(memberAvatarPath) == false)
|
||||
return MemberAvatarPath(member) == string.Empty ? GetGravatar(member.GetPropertyValue("Email").ToString(), avatarSize, member.Name) : GetLocalAvatar(member.GetPropertyValue("avatar").ToString(), avatarSize, member.Name);
|
||||
{
|
||||
return MemberAvatarPath(member) == string.Empty
|
||||
? GetGravatar(member.GetPropertyValue("Email").ToString(), avatarSize, member.Name, getRawUrl)
|
||||
: GetLocalAvatar(member.GetPropertyValue("avatar").ToString(), avatarSize, member.Name, getRawUrl);
|
||||
}
|
||||
|
||||
return GetGravatar(member.GetPropertyValue("Email").ToString(), avatarSize, member.Name);
|
||||
return GetGravatar(member.GetPropertyValue("Email").ToString(), avatarSize, member.Name, getRawUrl);
|
||||
}
|
||||
|
||||
private static string MemberAvatarPath(IPublishedContent member)
|
||||
@@ -288,18 +292,25 @@ namespace OurUmbraco.Our
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetGravatar(string email, int size, string memberName)
|
||||
public static string GetGravatar(string email, int size, string memberName, bool getRawUrl = false)
|
||||
{
|
||||
var emailId = email.ToLower();
|
||||
var hash = FormsAuthentication.HashPasswordForStoringInConfigFile(emailId, "MD5").ToLower();
|
||||
|
||||
return string.Format("<img src=\"//www.gravatar.com/avatar/{0}?s={1}&d=mm&r=g&d=retro\" alt=\"{2}\" />", hash, size, memberName);
|
||||
var url = string.Format("https://www.gravatar.com/avatar/{0}?s={1}&d=mm&r=g&d=retro", hash, size);
|
||||
|
||||
return !getRawUrl
|
||||
? string.Format("<img src=\"{0}\" alt=\"{1}\" />", url, memberName)
|
||||
: url;
|
||||
}
|
||||
|
||||
public static string GetLocalAvatar(string imgPath, int minSize, string memberName)
|
||||
public static string GetLocalAvatar(string imgPath, int minSize, string memberName, bool getRawUrl = false)
|
||||
{
|
||||
return string.Format("<img src=\"{0}?width={1}&height={1}&mode=crop\" srcset=\"{0}?width={2}&height={2}&mode=crop 2x, {0}?width={3}&height={3}&mode=crop 3x\" alt=\"{4}\" />",
|
||||
imgPath.Replace(" ", "%20"), minSize, (minSize * 2), (minSize * 3), memberName);
|
||||
var url = string.Format("{0}?width={1}&height={1}&mode=crop", imgPath.Replace(" ", "%20"), minSize);
|
||||
|
||||
return !getRawUrl
|
||||
? string.Format("<img src=\"{0}?width={1}&height={1}&mode=crop\" srcset=\"{0}?width={2}&height={2}&mode=crop 2x, {0}?width={3}&height={3}&mode=crop 3x\" alt=\"{4}\" />", imgPath.Replace(" ", "%20"), minSize, (minSize * 2), (minSize * 3), memberName)
|
||||
: url;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -624,12 +624,13 @@
|
||||
<Compile Include="Repository\Controllers\PackageSortOrder.cs" />
|
||||
<Compile Include="Repository\Models\Category.cs" />
|
||||
<Compile Include="Repository\Models\ExternalSource.cs" />
|
||||
<Compile Include="Repository\Models\PacakgeDetails.cs" />
|
||||
<Compile Include="Repository\Models\PackageDetails.cs" />
|
||||
<Compile Include="Repository\Models\Package.cs" />
|
||||
<Compile Include="Repository\Models\PackageCompatibility.cs" />
|
||||
<Compile Include="Repository\Models\PackageImage.cs" />
|
||||
<Compile Include="Repository\Models\PackageOwnerInfo.cs" />
|
||||
<Compile Include="Repository\Models\PagedPackages.cs" />
|
||||
<Compile Include="Repository\Services\PackageRepositoryService.cs" />
|
||||
<Compile Include="Repository\Project.cs" />
|
||||
<Compile Include="Repository\Projects.cs" />
|
||||
<Compile Include="Repository\RepoStartupHandler.cs" />
|
||||
|
||||
@@ -3,11 +3,12 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Cors;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using OurUmbraco.Repository.Models;
|
||||
using OurUmbraco.Repository.Services;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
using System.Net.Http;
|
||||
using System.Net;
|
||||
|
||||
namespace OurUmbraco.Repository.Controllers
|
||||
{
|
||||
@@ -19,206 +20,20 @@ namespace OurUmbraco.Repository.Controllers
|
||||
/// </remarks>
|
||||
[EnableCors(origins: "*", headers: "*", methods: "*")]
|
||||
[JsonCamelCaseFormatter]
|
||||
public class PackageRepositoryController : ApiController
|
||||
{
|
||||
public class PackageRepositoryController : UmbracoApiControllerBase
|
||||
{
|
||||
private readonly PackageRepositoryService Service;
|
||||
|
||||
private Models.PacakgeDetails GetTestDetails()
|
||||
public PackageRepositoryController()
|
||||
{
|
||||
return new Models.PacakgeDetails
|
||||
{
|
||||
Category = "Collaboration",
|
||||
Excerpt = "You will make me be president",
|
||||
Downloads = 123,
|
||||
Id = Guid.NewGuid(),
|
||||
Likes = 444,
|
||||
Name = "The Donald",
|
||||
Icon = "https://our.umbraco.org/media/wiki/150283/635768313097111400_usightlylogopng.png?bgcolor=fff&height=154&width=281&format=png",
|
||||
Created = DateTime.Now,
|
||||
Compatibility = new List<PackageCompatibility>
|
||||
{
|
||||
new PackageCompatibility
|
||||
{
|
||||
Percentage = 90,
|
||||
Version = "7.5.0"
|
||||
},
|
||||
new PackageCompatibility
|
||||
{
|
||||
Percentage = 100,
|
||||
Version = "7.4.0"
|
||||
}
|
||||
},
|
||||
NetVersion = "4.5.0",
|
||||
LatestVersion = "1.2.0",
|
||||
LicenseName = "MIT",
|
||||
LicenseUrl = "https://opensource.org/licenses/MIT",
|
||||
MinimumVersion = "7.4.0",
|
||||
OwnerInfo = new PackageOwnerInfo
|
||||
{
|
||||
Contributors = new[]
|
||||
{
|
||||
"Lee Kelleher",
|
||||
"Matt Brailsford"
|
||||
},
|
||||
Karma = 1000000,
|
||||
Owner = "Shannon Deminick",
|
||||
OwnerAvatar = "https://our.umbraco.org/media/upload/d476d257-a494-46d9-9a00-56c2f94a55c8/our-profile.jpg?width=200&height=200&mode=crop"
|
||||
},
|
||||
Description = "<p>This package is so great, I mean, it's really really good</p><p>It has lots of words because I know words, I have the best words</p>",
|
||||
Images = new List<PackageImage>
|
||||
{
|
||||
new PackageImage
|
||||
{
|
||||
Thumbnail = "https://our.umbraco.org/media/wiki/104946/635591947547374885_Product-Listpng.png?bgcolor=fff&height=154&width=281&format=png",
|
||||
Source = "https://our.umbraco.org/media/wiki/104946/635591947547374885_Product-Listpng.png"
|
||||
},
|
||||
new PackageImage
|
||||
{
|
||||
Thumbnail = "https://our.umbraco.org/media/wiki/104946/635591947547374885_Product-Listpng.png?bgcolor=fff&height=154&width=281&format=png",
|
||||
Source = "https://our.umbraco.org/media/wiki/104946/635591947547374885_Product-Listpng.png"
|
||||
},
|
||||
new PackageImage
|
||||
{
|
||||
Thumbnail = "https://our.umbraco.org/media/wiki/104946/635591947547374885_Product-Listpng.png?bgcolor=fff&height=154&width=281&format=png",
|
||||
Source = "https://our.umbraco.org/media/wiki/104946/635591947547374885_Product-Listpng.png"
|
||||
},
|
||||
new PackageImage
|
||||
{
|
||||
Thumbnail = "https://our.umbraco.org/media/wiki/104946/635591947547374885_Product-Listpng.png?bgcolor=fff&height=154&width=281&format=png",
|
||||
Source = "https://our.umbraco.org/media/wiki/104946/635591947547374885_Product-Listpng.png"
|
||||
}
|
||||
},
|
||||
ExternalSources = new List<ExternalSource>
|
||||
{
|
||||
new ExternalSource
|
||||
{
|
||||
Name = "Source code",
|
||||
Url = "https://github.com/merchello/Merchello"
|
||||
},
|
||||
new ExternalSource
|
||||
{
|
||||
Name = "Issue tracker",
|
||||
Url = "http://issues.merchello.com/youtrack/oauth?state=%2Fyoutrack%2FrootGo"
|
||||
}
|
||||
}
|
||||
};
|
||||
Service = new PackageRepositoryService(Umbraco, Members, DatabaseContext);
|
||||
}
|
||||
|
||||
private IEnumerable<Models.Package> GetTestData()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new Models.Package
|
||||
{
|
||||
Category = "Collaboration",
|
||||
Excerpt = "You will make me be president",
|
||||
Downloads = 123,
|
||||
Id = Guid.NewGuid(),
|
||||
Likes = 444,
|
||||
Name = "The Donald",
|
||||
Icon = "https://our.umbraco.org/media/wiki/150283/635768313097111400_usightlylogopng.png?bgcolor=fff&height=154&width=281&format=png",
|
||||
LatestVersion = "1.2.0",
|
||||
MinimumVersion = "7.4.0",
|
||||
OwnerInfo = new PackageOwnerInfo
|
||||
{
|
||||
Contributors = new[]
|
||||
{
|
||||
"Lee Kelleher",
|
||||
"Matt Brailsford"
|
||||
},
|
||||
Karma = 1000000,
|
||||
Owner = "Shannon Deminick",
|
||||
OwnerAvatar = "https://our.umbraco.org/media/upload/d476d257-a494-46d9-9a00-56c2f94a55c8/our-profile.jpg?width=200&height=200&mode=crop"
|
||||
}
|
||||
},
|
||||
new Models.Package
|
||||
{
|
||||
Category = "Starter Kits",
|
||||
Excerpt = "Another great package",
|
||||
Downloads = 123,
|
||||
Id = Guid.NewGuid(),
|
||||
Likes = 444,
|
||||
Name = "Kill IE6",
|
||||
Icon = "https://our.umbraco.org/media/wiki/9138/634697622367666000_offroadcode-100x100.png?bgcolor=fff&height=154&width=281&format=png",
|
||||
OwnerInfo = new PackageOwnerInfo
|
||||
{
|
||||
Contributors = new[]
|
||||
{
|
||||
"Lee Kelleher",
|
||||
"Matt Brailsford"
|
||||
},
|
||||
Karma = 1000000,
|
||||
Owner = "Shannon Deminick",
|
||||
OwnerAvatar = "https://our.umbraco.org/media/upload/d476d257-a494-46d9-9a00-56c2f94a55c8/our-profile.jpg?width=200&height=200&mode=crop"
|
||||
}
|
||||
},
|
||||
new Models.Package
|
||||
{
|
||||
Category = "Umbraco Pro",
|
||||
Excerpt = "A package for doing great things",
|
||||
Downloads = 123,
|
||||
Id = Guid.NewGuid(),
|
||||
Likes = 4,
|
||||
Name = "Great!",
|
||||
Icon = "https://our.umbraco.org/media/wiki/50703/634782902373558000_cogworks.jpg?bgcolor=fff&height=154&width=281&format=png",
|
||||
OwnerInfo = new PackageOwnerInfo
|
||||
{
|
||||
Contributors = new[]
|
||||
{
|
||||
"Lee Kelleher",
|
||||
"Matt Brailsford"
|
||||
},
|
||||
Karma = 1000000,
|
||||
Owner = "Shannon Deminick",
|
||||
OwnerAvatar = "https://our.umbraco.org/media/upload/d476d257-a494-46d9-9a00-56c2f94a55c8/our-profile.jpg?width=200&height=200&mode=crop"
|
||||
}
|
||||
},
|
||||
new Models.Package
|
||||
{
|
||||
Category = "Collaboration",
|
||||
Excerpt = "Super crazy awesome, this thing is just amazing",
|
||||
Downloads = 13323,
|
||||
Id = Guid.NewGuid(),
|
||||
Likes = 44334,
|
||||
Name = "Amazeballs",
|
||||
Icon = "https://our.umbraco.org/media/wiki/154472/635997115126742822_logopng.png?bgcolor=fff&height=154&width=281&format=png",
|
||||
OwnerInfo = new PackageOwnerInfo
|
||||
{
|
||||
Contributors = new[]
|
||||
{
|
||||
"Lee Kelleher",
|
||||
"Matt Brailsford"
|
||||
},
|
||||
Karma = 1000000,
|
||||
Owner = "Shannon Deminick",
|
||||
OwnerAvatar = "https://our.umbraco.org/media/upload/d476d257-a494-46d9-9a00-56c2f94a55c8/our-profile.jpg?width=200&height=200&mode=crop"
|
||||
}
|
||||
},
|
||||
new Models.Package
|
||||
{
|
||||
Category = "Starter Kits",
|
||||
Excerpt = "A classic, you just can't get enough of this one",
|
||||
Downloads = 12,
|
||||
Id = Guid.NewGuid(),
|
||||
Likes = 433,
|
||||
Name = "uBeMeAndIBeU",
|
||||
Icon = "https://our.umbraco.org/media/wiki/152476/635917291068518788_pipeline-crm-logopng.png?bgcolor=fff&height=154&width=281&format=png",
|
||||
OwnerInfo = new PackageOwnerInfo
|
||||
{
|
||||
Contributors = new[]
|
||||
{
|
||||
"Lee Kelleher",
|
||||
"Matt Brailsford"
|
||||
},
|
||||
Karma = 1000000,
|
||||
Owner = "Shannon Deminick",
|
||||
OwnerAvatar = "https://our.umbraco.org/media/upload/d476d257-a494-46d9-9a00-56c2f94a55c8/our-profile.jpg?width=200&height=200&mode=crop"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<Models.Category> GetCategories()
|
||||
{
|
||||
// [LK:2016-06-13@CGRT16] We're hardcoding the categories as the 'icon' isn't
|
||||
// content-manageable (yet). There is a media-picker icon, but that's for a different use.
|
||||
// When the time comes, we can switch to query for the Category nodes directly.
|
||||
return new[]
|
||||
{
|
||||
new Models.Category
|
||||
@@ -235,7 +50,7 @@ namespace OurUmbraco.Repository.Controllers
|
||||
{
|
||||
Icon = "icon-brackets",
|
||||
Name = "Developer tools"
|
||||
},
|
||||
},
|
||||
new Models.Category
|
||||
{
|
||||
Icon = "icon-wand",
|
||||
@@ -255,45 +70,26 @@ namespace OurUmbraco.Repository.Controllers
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public PagedPackages Search(int pageIndex, int pageSize,
|
||||
string category = null,
|
||||
string query = null,
|
||||
PackageSortOrder order = PackageSortOrder.Latest )
|
||||
public PagedPackages Search(
|
||||
int pageIndex,
|
||||
int pageSize,
|
||||
string category = null,
|
||||
string query = null,
|
||||
PackageSortOrder order = PackageSortOrder.Latest)
|
||||
{
|
||||
var packages = GetTestData()
|
||||
.Where(x => string.IsNullOrWhiteSpace(category) || x.Category == category)
|
||||
.Where(x => string.IsNullOrWhiteSpace(query) || x.Name.InvariantContains(query));
|
||||
|
||||
//TODO: This will be interesting - not sure if we are using Examine for searching but if we are
|
||||
// and if the query is not empty, then we should order by score,
|
||||
// otherwise if there is no query we will order by the 'order' parameter
|
||||
Models.Package[] sorted;
|
||||
if (string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
//TODO: order by score if possible
|
||||
sorted = packages.OrderBy(x => x.Created).ToArray();
|
||||
}
|
||||
else if (order == PackageSortOrder.Latest)
|
||||
{
|
||||
sorted = packages.OrderBy(x => x.Created).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: Also included downloads somehow?
|
||||
sorted = packages.OrderBy(x => x.Likes).ToArray();
|
||||
}
|
||||
|
||||
return new PagedPackages
|
||||
{
|
||||
Packages = sorted.Skip(pageIndex * pageSize).Take(pageSize),
|
||||
Total = sorted.Length
|
||||
};
|
||||
}
|
||||
|
||||
public Models.PacakgeDetails GetDetails(Guid id)
|
||||
{
|
||||
return GetTestDetails();
|
||||
return Service.GetPackages(pageIndex, pageSize, category, query, order);
|
||||
}
|
||||
|
||||
public Models.PackageDetails GetDetails(Guid id)
|
||||
{
|
||||
var package = Service.GetDetails(id);
|
||||
|
||||
if (package == null)
|
||||
{
|
||||
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
|
||||
}
|
||||
|
||||
return package;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace OurUmbraco.Repository.Models
|
||||
{
|
||||
public class PacakgeDetails : Package
|
||||
{
|
||||
public PacakgeDetails()
|
||||
{
|
||||
Images = new List<PackageImage>();
|
||||
Compatibility = new List<PackageCompatibility>();
|
||||
ExternalSources = new List<ExternalSource>();
|
||||
}
|
||||
public string Description { get; set; }
|
||||
public List<PackageImage> Images { get; set; }
|
||||
public List<PackageCompatibility> Compatibility { get; set; }
|
||||
public List<ExternalSource> ExternalSources { get; set; }
|
||||
public string LicenseName { get; set; }
|
||||
public string LicenseUrl { get; set; }
|
||||
public string NetVersion { get; set; }
|
||||
public string ZipUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OurUmbraco.Repository.Models
|
||||
{
|
||||
@@ -11,16 +8,27 @@ namespace OurUmbraco.Repository.Models
|
||||
{
|
||||
OwnerInfo = new PackageOwnerInfo();
|
||||
}
|
||||
|
||||
public DateTime Created { get; set; }
|
||||
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Excerpt { get; set; }
|
||||
|
||||
public string Icon { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
public int Downloads { get; set; }
|
||||
|
||||
public int Likes { get; set; }
|
||||
|
||||
public string Category { get; set; }
|
||||
|
||||
public string LatestVersion { get; set; }
|
||||
|
||||
public PackageOwnerInfo OwnerInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -31,4 +39,4 @@ namespace OurUmbraco.Repository.Models
|
||||
/// </remarks>
|
||||
public string MinimumVersion { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OurUmbraco.Repository.Models
|
||||
{
|
||||
public class PackageDetails : Package
|
||||
{
|
||||
public PackageDetails()
|
||||
{
|
||||
Images = new List<PackageImage>();
|
||||
Compatibility = new List<PackageCompatibility>();
|
||||
ExternalSources = new List<ExternalSource>();
|
||||
}
|
||||
|
||||
public PackageDetails(Package package)
|
||||
: base()
|
||||
{
|
||||
if (package != null)
|
||||
{
|
||||
this.Category = package.Category;
|
||||
this.Excerpt = package.Excerpt;
|
||||
this.Downloads = package.Downloads;
|
||||
this.Id = package.Id;
|
||||
this.Likes = package.Likes;
|
||||
this.Name = package.Name;
|
||||
this.Icon = package.Icon;
|
||||
this.LatestVersion = package.LatestVersion;
|
||||
this.MinimumVersion = package.MinimumVersion;
|
||||
this.OwnerInfo = package.OwnerInfo;
|
||||
}
|
||||
}
|
||||
|
||||
public string Description { get; set; }
|
||||
|
||||
public List<PackageImage> Images { get; set; }
|
||||
|
||||
public List<PackageCompatibility> Compatibility { get; set; }
|
||||
|
||||
public List<ExternalSource> ExternalSources { get; set; }
|
||||
|
||||
public string LicenseName { get; set; }
|
||||
|
||||
public string LicenseUrl { get; set; }
|
||||
|
||||
public string NetVersion { get; set; }
|
||||
|
||||
public string ZipUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace OurUmbraco.Repository
|
||||
RouteTable.Routes.MapHttpRoute(
|
||||
name: "PackageRepositoryApi",
|
||||
routeTemplate: "webapi/packages/v1/{id}",
|
||||
defaults: new { id = RouteParameter.Optional, controller = "PackageRepository"},
|
||||
defaults: new { id = RouteParameter.Optional, controller = "PackageRepository" },
|
||||
constraints: new { }
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Examine;
|
||||
using OurUmbraco.Forum.Extensions;
|
||||
using OurUmbraco.MarketPlace.Providers;
|
||||
using OurUmbraco.Our;
|
||||
using OurUmbraco.Project.Services;
|
||||
using OurUmbraco.Repository.Controllers;
|
||||
using OurUmbraco.Repository.Models;
|
||||
using OurUmbraco.Wiki.BusinessLogic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Security;
|
||||
|
||||
namespace OurUmbraco.Repository.Services
|
||||
{
|
||||
internal class PackageRepositoryService
|
||||
{
|
||||
private readonly DatabaseContext DatabaseContext;
|
||||
private readonly MembershipHelper MembershipHelper;
|
||||
private readonly UmbracoHelper UmbracoHelper;
|
||||
|
||||
const string BASE_URL = "https://our.umbraco.org";
|
||||
|
||||
public PackageRepositoryService(UmbracoHelper umbracoHelper, MembershipHelper membershipHelper, DatabaseContext databaseContext)
|
||||
{
|
||||
UmbracoHelper = umbracoHelper;
|
||||
MembershipHelper = membershipHelper;
|
||||
DatabaseContext = databaseContext;
|
||||
}
|
||||
|
||||
public IEnumerable<Models.Category> GetCategories()
|
||||
{
|
||||
var xpath = "//ProjectGroup[@isDoc]";
|
||||
var helper = new UmbracoHelper(UmbracoContext.Current);
|
||||
|
||||
var items = helper.TypedContentAtXPath(xpath);
|
||||
|
||||
return items
|
||||
.OrderBy(x => x.SortOrder)
|
||||
.Select(x => new Models.Category
|
||||
{
|
||||
Icon = "",
|
||||
Name = x.Name
|
||||
});
|
||||
}
|
||||
|
||||
public PagedPackages GetPackages(
|
||||
int pageIndex,
|
||||
int pageSize,
|
||||
string category = null,
|
||||
string query = null,
|
||||
PackageSortOrder order = PackageSortOrder.Latest)
|
||||
{
|
||||
var items = Enumerable.Empty<IPublishedContent>();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(category) && string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
if (order == PackageSortOrder.Latest)
|
||||
{
|
||||
// [LK:2016-06-13@CGRT16] This feels hacky, but unsure how else to get
|
||||
// a list of all the newly created projects.
|
||||
var xpath = "//Project[@isDoc and projectLive = 1 and approved = 1 and notAPackage = 0]";
|
||||
items = UmbracoHelper
|
||||
.TypedContentAtXPath(xpath)
|
||||
.OrderByDescending(x => x.CreateDate);
|
||||
}
|
||||
else
|
||||
{
|
||||
// [LK:2016-06-13@CGRT16] Attempting to reuse legacy code
|
||||
var karmaProvider = new KarmaProvider();
|
||||
var projectsByKarma = karmaProvider.GetProjectsKarmaList();
|
||||
|
||||
items = UmbracoHelper
|
||||
.TypedContent(projectsByKarma.Select(x => x.ProjectId))
|
||||
.Where(x =>
|
||||
x.GetPropertyValue<bool>("projectLive") &&
|
||||
x.GetPropertyValue<bool>("approved") &&
|
||||
!x.GetPropertyValue<bool>("notAPackage"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var q = new StringBuilder();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(category))
|
||||
{
|
||||
q.AppendFormat("+categoryFolder: \"{0}\" ", category);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
q.AppendFormat("+nodeName:{0}", query);
|
||||
}
|
||||
|
||||
var searcher = ExamineManager.Instance.SearchProviderCollection["projectSearcher"];
|
||||
var criteria = searcher.CreateSearchCriteria().RawQuery(q.ToString());
|
||||
|
||||
items = UmbracoHelper.TypedSearch(criteria, searcher);
|
||||
}
|
||||
|
||||
if (items == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var packages = items
|
||||
.Skip(pageIndex * pageSize)
|
||||
.Take(pageSize)
|
||||
.Select(x => MapContentToPackage(x));
|
||||
|
||||
IEnumerable<Models.Package> sorted;
|
||||
|
||||
if (order == PackageSortOrder.Latest)
|
||||
{
|
||||
sorted = packages
|
||||
.OrderByDescending(x => x.Created);
|
||||
}
|
||||
else
|
||||
{
|
||||
sorted = packages
|
||||
.OrderByDescending(x => x.Downloads)
|
||||
.ThenByDescending(x => x.Likes);
|
||||
}
|
||||
|
||||
return new PagedPackages
|
||||
{
|
||||
Packages = packages,
|
||||
Total = items.Count()
|
||||
};
|
||||
}
|
||||
|
||||
public Models.PackageDetails GetDetails(Guid id)
|
||||
{
|
||||
// [LK:2016-06-13@CGRT16] We're using XPath as we experienced issues with query Examine for GUIDs,
|
||||
// (it might worth but we were up against the clock).
|
||||
// The XPath 'translate' is being used to force the 'packageGuid' to be lowercase for comparison.
|
||||
var xpath = string.Format("//Project[@isDoc and projectLive = 1 and approved = 1 and translate(packageGuid,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz') = '{0}']", id.ToString("D").ToLowerInvariant());
|
||||
var item = UmbracoHelper.TypedContentSingleAtXPath(xpath);
|
||||
|
||||
if (item == null)
|
||||
return null;
|
||||
|
||||
return MapContentToPackageDetails(item);
|
||||
}
|
||||
|
||||
private Models.Package MapContentToPackage(IPublishedContent content)
|
||||
{
|
||||
if (content == null)
|
||||
return null;
|
||||
|
||||
var wikiFiles = WikiFile.CurrentFiles(content.Id);
|
||||
|
||||
return new Models.Package
|
||||
{
|
||||
Category = content.Parent.Name,
|
||||
Created = content.CreateDate,
|
||||
Excerpt = GetPackageExcerpt(content, 12),
|
||||
Downloads = Utils.GetProjectTotalDownloadCount(content.Id),
|
||||
Id = content.GetPropertyValue<Guid>("packageGuid"),
|
||||
Likes = Utils.GetProjectTotalVotes(content.Id),
|
||||
Name = content.Name,
|
||||
Icon = GetThumbnailUrl(BASE_URL + content.GetPropertyValue<string>("defaultScreenshotPath", "/css/img/package2.png"), 154, 281),
|
||||
LatestVersion = content.GetPropertyValue<string>("version"),
|
||||
MinimumVersion = GetMinimumVersion(content, wikiFiles.Where(x => x.FileType.InvariantEquals("package"))),
|
||||
OwnerInfo = GetPackageOwnerInfo(content),
|
||||
Url = string.Concat(BASE_URL, content.Url)
|
||||
};
|
||||
}
|
||||
|
||||
private Models.PackageDetails MapContentToPackageDetails(IPublishedContent content)
|
||||
{
|
||||
if (content == null)
|
||||
return null;
|
||||
|
||||
var package = MapContentToPackage(content);
|
||||
var packageDetails = new PackageDetails(package);
|
||||
var wikiFiles = WikiFile.CurrentFiles(content.Id);
|
||||
|
||||
packageDetails.Compatibility = GetPackageCompatibility(content);
|
||||
packageDetails.NetVersion = content.GetPropertyValue<string>("dotNetVersion");
|
||||
packageDetails.LicenseName = content.GetPropertyValue<string>("licenseName");
|
||||
packageDetails.LicenseUrl = content.GetPropertyValue<string>("licenseUrl");
|
||||
packageDetails.Description = content.GetPropertyValue<string>("description");
|
||||
packageDetails.Images = GetPackageImages(wikiFiles.Where(x => x.FileType.InvariantEquals("screenshot")), 154, 281);
|
||||
packageDetails.ExternalSources = GetExternalSources(content);
|
||||
packageDetails.ZipUrl = string.Concat(BASE_URL, "/FileDownload?id=", content.GetPropertyValue<string>("file"));
|
||||
|
||||
return packageDetails;
|
||||
}
|
||||
|
||||
private List<PackageCompatibility> GetPackageCompatibility(IPublishedContent content)
|
||||
{
|
||||
var service = new VersionCompatibilityService(DatabaseContext);
|
||||
var report = service.GetCompatibilityReport(content.Id);
|
||||
|
||||
if (report == null || !report.Any())
|
||||
return null;
|
||||
|
||||
return report
|
||||
.Select(x => new PackageCompatibility
|
||||
{
|
||||
Percentage = x.Percentage,
|
||||
Version = x.Version
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private string GetMinimumVersion(IPublishedContent content, IEnumerable<WikiFile> packages)
|
||||
{
|
||||
var currentVersion = content.GetPropertyValue<int>("file");
|
||||
var latest = packages.FirstOrDefault(x => x.Id == currentVersion);
|
||||
|
||||
if (latest == null || string.IsNullOrWhiteSpace(latest.Version.Version) || latest.Version.Version.InvariantEquals("nan"))
|
||||
return null;
|
||||
|
||||
if (latest.Version.Version.InvariantStartsWith("v"))
|
||||
{
|
||||
var legacyFormat = latest.Version.Version;
|
||||
|
||||
if (legacyFormat.InvariantStartsWith("v4"))
|
||||
{
|
||||
return string.Concat(legacyFormat.Replace("v4", "4."), ".0");
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Join(".", legacyFormat.ToCharArray().Skip(1));
|
||||
}
|
||||
}
|
||||
|
||||
return latest.Version.Version;
|
||||
}
|
||||
|
||||
private PackageOwnerInfo GetPackageOwnerInfo(IPublishedContent content)
|
||||
{
|
||||
var ownerId = content.GetPropertyValue<int>("owner");
|
||||
var owner = MembershipHelper.GetById(ownerId);
|
||||
|
||||
var ownerInfo = new PackageOwnerInfo
|
||||
{
|
||||
Karma = owner.Karma(),
|
||||
Owner = owner.Name,
|
||||
OwnerAvatar = Utils.GetMemberAvatar(owner, 200, true)
|
||||
};
|
||||
|
||||
if (content.GetPropertyValue<bool>("openForCollab", false))
|
||||
{
|
||||
var service = new ContributionService(DatabaseContext);
|
||||
var contributors = service.GetContributors(content.Id).ToList();
|
||||
|
||||
if (contributors != null && contributors.Any())
|
||||
{
|
||||
var names = new List<string>();
|
||||
|
||||
foreach (var contributor in contributors)
|
||||
{
|
||||
var member = MembershipHelper.GetById(contributor.MemberId);
|
||||
if (member != null)
|
||||
{
|
||||
names.Add(member.Name);
|
||||
}
|
||||
}
|
||||
|
||||
ownerInfo.Contributors = names.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
return ownerInfo;
|
||||
}
|
||||
|
||||
private List<PackageImage> GetPackageImages(IEnumerable<WikiFile> images, int thumbnailHeight, int thumbnailWidth)
|
||||
{
|
||||
var items = new List<PackageImage>();
|
||||
|
||||
foreach (var image in images)
|
||||
{
|
||||
var url = string.Concat(BASE_URL, image.Path);
|
||||
|
||||
items.Add(new PackageImage
|
||||
{
|
||||
Source = url,
|
||||
Thumbnail = GetThumbnailUrl(url, thumbnailHeight, thumbnailWidth)
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private string GetThumbnailUrl(string url, int height, int width)
|
||||
{
|
||||
return string.Format("{0}?bgcolor=fff&height={1}&width={2}&format=png", url, height, width);
|
||||
}
|
||||
|
||||
private List<ExternalSource> GetExternalSources(IPublishedContent content)
|
||||
{
|
||||
var items = new List<ExternalSource>();
|
||||
|
||||
if (content.HasValue("websiteUrl"))
|
||||
{
|
||||
items.Add(new ExternalSource
|
||||
{
|
||||
Name = "Project website",
|
||||
Url = content.GetPropertyValue<string>("websiteUrl")
|
||||
});
|
||||
}
|
||||
|
||||
if (content.HasValue("sourceUrl"))
|
||||
{
|
||||
items.Add(new ExternalSource
|
||||
{
|
||||
Name = "Source code",
|
||||
Url = content.GetPropertyValue<string>("sourceUrl")
|
||||
});
|
||||
}
|
||||
|
||||
if (content.HasValue("demoUrl"))
|
||||
{
|
||||
items.Add(new ExternalSource
|
||||
{
|
||||
Name = "Demonstration",
|
||||
Url = content.GetPropertyValue<string>("demoUrl")
|
||||
});
|
||||
}
|
||||
|
||||
if (content.HasValue("supportUrl"))
|
||||
{
|
||||
items.Add(new ExternalSource
|
||||
{
|
||||
Name = "Issue tracker",
|
||||
Url = content.GetPropertyValue<string>("supportUrl")
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private string GetPackageExcerpt(IPublishedContent content, int count = 35)
|
||||
{
|
||||
var input = content.GetPropertyValue<string>("description");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return null;
|
||||
|
||||
var words = input
|
||||
.StripHtml()
|
||||
.StripNewLines()
|
||||
.Replace(" ", " ")
|
||||
.Split(new[] { ' ' })
|
||||
.Take(count)
|
||||
.ToList();
|
||||
|
||||
return string.Concat(string.Join(" ", words), "...");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -386,6 +386,11 @@ namespace OurUmbraco.Wiki.BusinessLogic
|
||||
{
|
||||
if (UmbracoVersion.AvailableVersions().ContainsKey(ver))
|
||||
umbracoVersions.Add(UmbracoVersion.AvailableVersions()[ver]);
|
||||
|
||||
// [LK:2016-06-13@CGRT16] Added to support v7.5+ package repository REST API
|
||||
System.Version v;
|
||||
if (System.Version.TryParse(ver, out v))
|
||||
umbracoVersions.Add(new UmbracoVersion { Version = v.ToString(3) });
|
||||
}
|
||||
|
||||
return umbracoVersions;
|
||||
|
||||
Reference in New Issue
Block a user