Files
Umbraco-CMS/src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs
2021-09-15 13:40:08 +02:00

193 lines
7.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Models.Trees;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Trees;
using Umbraco.Cms.Infrastructure.Search;
using Umbraco.Cms.Web.Common.Attributes;
using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Extensions;
using Constants = Umbraco.Cms.Core.Constants;
namespace Umbraco.Cms.Web.BackOffice.Trees
{
[Authorize(Policy = AuthorizationPolicies.SectionAccessForMediaTree)]
[Tree(Constants.Applications.Media, Constants.Trees.Media)]
[PluginController(Constants.Web.Mvc.BackOfficeTreeArea)]
[CoreTree]
[SearchableTree("searchResultFormatter", "configureMediaResult", 20)]
public class MediaTreeController : ContentTreeControllerBase, ISearchableTree, ITreeNodeController
{
private readonly UmbracoTreeSearcher _treeSearcher;
private readonly IMediaService _mediaService;
private readonly AppCaches _appCaches;
private readonly IEntityService _entityService;
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
public MediaTreeController(
ILocalizedTextService localizedTextService,
UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection,
IMenuItemCollectionFactory menuItemCollectionFactory,
IEntityService entityService,
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
ILogger<MediaTreeController> logger,
ActionCollection actionCollection,
IUserService userService,
IDataTypeService dataTypeService,
UmbracoTreeSearcher treeSearcher,
IMediaService mediaService,
IEventAggregator eventAggregator,
AppCaches appCaches)
: base(localizedTextService, umbracoApiControllerTypeCollection, menuItemCollectionFactory, entityService, backofficeSecurityAccessor, logger, actionCollection, userService, dataTypeService, eventAggregator, appCaches)
{
_treeSearcher = treeSearcher;
_mediaService = mediaService;
_appCaches = appCaches;
_entityService = entityService;
_backofficeSecurityAccessor = backofficeSecurityAccessor;
}
protected override int RecycleBinId => Constants.System.RecycleBinMedia;
protected override bool RecycleBinSmells => _mediaService.RecycleBinSmells();
private int[] _userStartNodes;
protected override int[] UserStartNodes
=> _userStartNodes ?? (_userStartNodes = _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.CalculateMediaStartNodeIds(_entityService, _appCaches));
/// <summary>
/// Creates a tree node for a content item based on an UmbracoEntity
/// </summary>
/// <param name="e"></param>
/// <param name="parentId"></param>
/// <param name="queryStrings"></param>
/// <returns></returns>
protected override TreeNode GetSingleTreeNode(IEntitySlim entity, string parentId, FormCollection queryStrings)
{
var node = CreateTreeNode(
entity,
Constants.ObjectTypes.Media,
parentId,
queryStrings,
entity.HasChildren);
// entity is either a container, or a media
if (entity.IsContainer)
{
node.SetContainerStyle();
node.AdditionalData.Add("isContainer", true);
}
else
{
var contentEntity = (IContentEntitySlim) entity;
node.AdditionalData.Add("contentType", contentEntity.ContentTypeAlias);
}
return node;
}
protected override ActionResult<MenuItemCollection> PerformGetMenuForNode(string id, FormCollection queryStrings)
{
var menu = MenuItemCollectionFactory.Create();
//set the default
menu.DefaultMenuAlias = ActionNew.ActionAlias;
if (id == Constants.System.RootString)
{
// if the user's start node is not the root then the only menu item to display is refresh
if (UserStartNodes.Contains(Constants.System.Root) == false)
{
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
}
// root actions
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionSort>(LocalizedTextService, true, opensDialog: true);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
}
if (int.TryParse(id, NumberStyles.Integer, CultureInfo.InvariantCulture, out var iid) == false)
{
return NotFound();
}
var item = _entityService.Get(iid, UmbracoObjectTypes.Media);
if (item == null)
{
return NotFound();
}
//if the user has no path access for this node, all they can do is refresh
if (!_backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser.HasMediaPathAccess(item, _entityService, _appCaches))
{
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
return menu;
}
//if the media item is in the recycle bin, we don't have a default menu and we need to show a limited menu
if (item.Path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries).Contains(RecycleBinId.ToInvariantString()))
{
menu.Items.Add<ActionRestore>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionMove>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
menu.DefaultMenuAlias = null;
}
else
{
//return a normal node menu:
menu.Items.Add<ActionNew>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionMove>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionDelete>(LocalizedTextService, opensDialog: true);
menu.Items.Add<ActionSort>(LocalizedTextService);
menu.Items.Add(new RefreshNode(LocalizedTextService, true));
//set the default to create
menu.DefaultMenuAlias = ActionNew.ActionAlias;
}
return menu;
}
protected override UmbracoObjectTypes UmbracoObjectType => UmbracoObjectTypes.Media;
/// <summary>
/// Returns true or false if the current user has access to the node based on the user's allowed start node (path) access
/// </summary>
/// <param name="id"></param>
/// <param name="queryStrings"></param>
/// <returns></returns>
protected override bool HasPathAccess(string id, FormCollection queryStrings)
{
var entity = GetEntityFromId(id);
return HasPathAccess(entity, queryStrings);
}
public IEnumerable<SearchResultEntity> Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null)
{
return _treeSearcher.ExamineSearch(query, UmbracoEntityTypes.Media, pageSize, pageIndex, out totalFound, searchFrom);
}
}
}