Merge pull request #88 from leekelleher/feature/pkgrepo-restapi

Package Repo REST API
This commit is contained in:
Shannon Deminick
2016-06-13 23:12:04 +02:00
committed by GitHub
10 changed files with 477 additions and 274 deletions
@@ -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
View File
@@ -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;
}
}
+2 -1
View File
@@ -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; }
}
}
+12 -4
View File
@@ -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; }
}
}
+1 -1
View File
@@ -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("&nbsp;", " ")
.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;