Last active
June 2, 2020 15:36
-
-
Save nathanwoulfe/a5186667fca1a53c48088df13bfa65ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net; | |
using System.Web.Http; | |
using Umbraco.Core; | |
using Umbraco.Core.Models; | |
using Umbraco.Core.Services; | |
using Umbraco.Web; | |
using Umbraco.Web.WebApi; | |
namespace Api.SiteAdmin | |
{ | |
public class MediaManagerController : UmbracoAuthorizedApiController | |
{ | |
private readonly DatabaseContext _dbContext; | |
private readonly IMediaService _mediaService; | |
private const string ImgMediaQuery = | |
@"SELECT nodeId from cmsMedia | |
WHERE cmsMedia.nodeId not in (select distinct parentId from umbracoRelation where parentId is not null) | |
AND cmsMedia.nodeId not in (select distinct childId from umbracoRelation where childId is not null) | |
AND (cmsMedia.mediaPath like '%.png' OR cmsMedia.mediaPath like '%.jpg')"; | |
private const string DocsMediaQuery = | |
@"SELECT nodeId from cmsMedia | |
WHERE cmsMedia.nodeId not in (select distinct parentId from umbracoRelation where parentId is not null) | |
AND cmsMedia.nodeId not in (select distinct childId from umbracoRelation where childId is not null) | |
AND ( | |
cmsMedia.mediaPath not like '%.png' | |
AND cmsMedia.mediaPath not like '%.jpg' | |
AND cmsMedia.mediaPath not like '%.svg' | |
AND cmsMedia.mediaPath not like '%.css' | |
AND cmsMedia.mediaPath not like '%.js')"; | |
// bit clunky, but should ignore non-standard stuff like css, js, svg etc | |
// these are used in canvas pages, so while archiving won't break anything, should leave them alone | |
private const string MediaQuery = | |
@"SELECT nodeId from cmsMedia | |
WHERE cmsMedia.nodeId not in (select distinct parentId from umbracoRelation where parentId is not null) | |
AND cmsMedia.nodeId not in (select distinct childId from umbracoRelation where childId is not null) | |
AND ( | |
cmsMedia.mediaPath not like '%.svg' | |
AND cmsMedia.mediaPath not like '%.css' | |
AND cmsMedia.mediaPath not like '%.js')"; | |
public MediaManagerController(DatabaseContext dbContext, IMediaService mediaService) | |
{ | |
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); | |
_mediaService = mediaService ?? throw new ArgumentNullException(nameof(mediaService)); | |
} | |
/// <summary> | |
/// | |
/// </summary> | |
/// <returns></returns> | |
[HttpGet] | |
public IHttpActionResult GetUnusedMedia() | |
{ | |
return Json(new | |
{ | |
status = HttpStatusCode.OK, | |
data = _dbContext.Database.Query<int>(MediaQuery) | |
}); | |
} | |
/// <summary> | |
/// | |
/// </summary> | |
/// <returns></returns> | |
[HttpGet] | |
public IHttpActionResult DeleteAll(string type) | |
{ | |
var items = _dbContext.Database.Query<int>(type == "images" ? ImgMediaQuery : type == "documents" ? DocsMediaQuery : MediaQuery); | |
return Json(new | |
{ | |
status = HttpStatusCode.OK, | |
data = TryDoDelete(items) | |
}); | |
} | |
[HttpPost] | |
public IHttpActionResult DeleteSelected(int[] ids) | |
{ | |
return Json(new | |
{ | |
status = HttpStatusCode.OK, | |
data = TryDoDelete(ids) | |
}); | |
} | |
private bool TryDoDelete(IEnumerable<int> ids) | |
{ | |
var success = false; | |
var hub = new NotificationsHub(); | |
hub.SendMessage("Fetching media to archive"); | |
try | |
{ | |
var root = CheckArchiveFolderStructure(); | |
var imageArchive = root.Children().FirstOrDefault(x => x.Name == "Images"); | |
var docsArchive = root.Children().FirstOrDefault(x => x.Name == "Documents"); | |
var imageYears = imageArchive.Children(); | |
var docsYears = docsArchive.Children(); | |
IEnumerable<IMedia> mediaItems = _mediaService.GetByIds(ids).Where(x => !x.Path.Contains(root.Id.ToString())); | |
hub.SendMessage($"Archiving {mediaItems.Count()} media items"); | |
var i = 1; | |
foreach (var mediaItem in mediaItems) | |
{ | |
var targetYear = (mediaItem.CreateDate.Year <= 2013 ? 2013 : mediaItem.CreateDate.Year).ToString(); | |
_mediaService.Move(mediaItem, (mediaItem.ContentType.Alias == KnownDocumentAlias.Media.Image ? imageYears : docsYears).First(x => x.Name == targetYear).Id); | |
if (i % 5 == 0) | |
{ | |
hub.SendMessage($"Still going - archived {i} media items"); | |
} | |
i += 1; | |
} | |
success = true; | |
} catch | |
{ | |
return false; | |
} | |
success = CleanEmptyFolders(); | |
hub.SendMessage("Media archiving complete"); | |
return success; | |
} | |
private bool CleanEmptyFolders() | |
{ | |
try | |
{ | |
var folders = _mediaService.GetMediaOfMediaType((int)KnownMediaTypeIds.Folder); | |
foreach (var folder in folders) | |
{ | |
if (!folder.Children().Any()) | |
{ | |
_mediaService.Delete(folder); | |
} | |
} | |
} catch | |
{ | |
return false; | |
} | |
return true; | |
} | |
/// <summary> | |
/// Ensure the media archive exists, if not create it - root level folders for type (img/file), then by year | |
/// </summary> | |
private IMedia CheckArchiveFolderStructure() | |
{ | |
var root = _mediaService.GetRootMedia().FirstOrDefault(x => x.ContentType.Alias == KnownDocumentAlias.Media.ArchiveFolder); | |
// create root if needed | |
if (root == null) | |
{ | |
root = _mediaService.CreateMedia("Archive", -1, KnownDocumentAlias.Media.ArchiveFolder); | |
_mediaService.Save(root); | |
} | |
// create image/docs folders if needed | |
if (!root.Children().Any()) | |
{ | |
_mediaService.Save(new[] { | |
_mediaService.CreateMedia("Images", root, KnownDocumentAlias.Media.ArchiveFolder), | |
_mediaService.CreateMedia("Documents", root, KnownDocumentAlias.Media.ArchiveFolder) | |
}); | |
} | |
// add years for each file type - five prior to current | |
foreach (var folder in root.Children()) | |
{ | |
// first run will create year folders back to 2013 | |
if (!folder.Children().Any()) | |
{ | |
for (var i = 0; i <= 6; i += 1) | |
{ | |
var year = DateTime.Now.Year - i; | |
var yearFolder = _mediaService.CreateMedia(year.ToString(), folder, KnownDocumentAlias.Media.ArchiveFolder); | |
_mediaService.Save(yearFolder); | |
} | |
} | |
// always check a folder exists for the current year | |
var currentYear = folder.Children().FirstOrDefault(x => x.Name == DateTime.Now.Year.ToString()); | |
if (currentYear == null) | |
{ | |
currentYear = _mediaService.CreateMedia(DateTime.Now.Year.ToString(), folder, KnownDocumentAlias.Media.ArchiveFolder); | |
_mediaService.Save(currentYear); | |
} | |
} | |
return root; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment