Ver Fonte

Added "AutoRefresh" poster class

Kenric Nugteren há 1 ano atrás
pai
commit
7184e4dfdb

+ 24 - 0
InABox.Core/Postable/IPoster.cs

@@ -19,11 +19,35 @@ namespace InABox.Core
         TSettings Settings { get; set; }
     }
 
+    /// <summary>
+    /// An interface to declare that an <see cref="IPoster{TEntity, TSettings}"/> provides a means to determine if a given <typeparamref name="TEntity"/>
+    /// needs to be reposted. This function is to be called on the server side when a <typeparamref name="TEntity"/> is saved.
+    /// </summary>
+    /// <typeparam name="TEntity"></typeparam>
+    public interface IAutoRefreshPoster<TEntity, TAutoRefresher>
+        where TAutoRefresher : IAutoRefresher<TEntity>
+    {
+    }
+
+    public interface IAutoRefresher<TEntity>
+    {
+        /// <summary>
+        /// Return <see langword="true"/> if <paramref name="entity"/> should be reposted, which will update its <see cref="IPostable.PostedStatus"/> to
+        /// <see cref="PostedStatus.RequiresRepost"/>.
+        /// </summary>
+        /// <param name="entity"></param>
+        /// <returns></returns>
+        bool ShouldRepost(TEntity entity);
+    }
+
     public interface IGlobalSettingsPoster
     {
         public IGlobalPosterSettings GlobalSettings { get; set; }
     }
 
+    /// <summary>
+    /// Declares that an <see cref="IPoster{TEntity, TSettings}"/> has global, entity-independent settings.
+    /// </summary>
     public interface IGlobalSettingsPoster<TGlobalSettings> : IGlobalSettingsPoster
         where TGlobalSettings : BaseObject, IGlobalPosterSettings
     {

+ 4 - 0
InABox.Core/Postable/PostableSettings.cs

@@ -26,5 +26,9 @@ namespace InABox.Core
 
         [EditorSequence(3)]
         public ImageDocumentLink Thumbnail { get; set; }
+
+        [EditorSequence(4)]
+        [CheckBoxEditor]
+        public bool ShowClearButton { get; set; } = true;
     }
 }

+ 100 - 44
InABox.Core/Postable/PosterUtils.cs

@@ -11,54 +11,14 @@ namespace InABox.Core
 {
     public static class PosterUtils
     {
-        private class EngineType
-        {
-            public Type Engine { get; set; }
-
-            public Type Entity { get; set; }
-
-            public Type Poster { get; set; }
-        }
-
-        private static EngineType[]? _posterEngines;
-        private static Type[]? _posters = null;
-
-        public static Type[] GetPosters()
-        {
-            _posters ??= CoreUtils.TypeList(
-                AppDomain.CurrentDomain.GetAssemblies(),
-                x => x.IsClass
-                    && !x.IsAbstract
-                    && !x.IsGenericType
-                    && x.HasInterface(typeof(IPoster<,>))).ToArray();
-            return _posters;
-        }
-
-        private static EngineType[] GetPosterEngines()
-        {
-            _posterEngines ??= CoreUtils.TypeList(
-                AppDomain.CurrentDomain.GetAssemblies(),
-                x => x.IsClass
-                    && !x.IsAbstract
-                    && x.GetTypeInfo().GenericTypeParameters.Length == 1
-                    && x.HasInterface(typeof(IPosterEngine<,,>))
-            ).Select(x => new EngineType
-            {
-                Engine = x,
-                Entity = x.GetInterfaceDefinition(typeof(IPosterEngine<,,>))!.GenericTypeArguments[0],
-                Poster = x.GetInterfaceDefinition(typeof(IPosterEngine<,,>))!.GenericTypeArguments[1].GetGenericTypeDefinition()
-            }).ToArray();
-            return _posterEngines;
-        }
 
         #region Postable Settings
 
-        private static PostableSettings FixPostableSettings<TPostable>(PostableSettings settings)
-            where TPostable : Entity, IPostable
+        private static PostableSettings FixPostableSettings(Type TPostable, PostableSettings settings)
         {
             if (string.IsNullOrWhiteSpace(settings.PostableType))
             {
-                settings.PostableType = typeof(TPostable).EntityName();
+                settings.PostableType = TPostable.EntityName();
             }
             return settings;
         }
@@ -66,13 +26,13 @@ namespace InABox.Core
         public static PostableSettings LoadPostableSettings<T>()
             where T : Entity, IPostable
         {
-            return FixPostableSettings<T>(new GlobalConfiguration<PostableSettings>(typeof(T).Name).Load());
+            return FixPostableSettings(typeof(T), new GlobalConfiguration<PostableSettings>(typeof(T).Name).Load());
         }
 
         public static void SavePostableSettings<T>(PostableSettings settings)
             where T : Entity, IPostable
         {
-            new GlobalConfiguration<PostableSettings>(typeof(T).Name).Save(FixPostableSettings<T>(settings));
+            new GlobalConfiguration<PostableSettings>(typeof(T).Name).Save(FixPostableSettings(typeof(T), settings));
         }
 
         #endregion
@@ -155,6 +115,48 @@ namespace InABox.Core
 
         #endregion
 
+        #region Poster Engines
+
+        private class EngineType
+        {
+            public Type Engine { get; set; }
+
+            public Type Entity { get; set; }
+
+            public Type Poster { get; set; }
+        }
+
+        private static EngineType[]? _posterEngines;
+        private static Type[]? _posters = null;
+
+        public static Type[] GetPosters()
+        {
+            _posters ??= CoreUtils.TypeList(
+                AppDomain.CurrentDomain.GetAssemblies(),
+                x => x.IsClass
+                    && !x.IsAbstract
+                    && !x.IsGenericType
+                    && x.HasInterface(typeof(IPoster<,>))).ToArray();
+            return _posters;
+        }
+
+        private static EngineType[] GetPosterEngines()
+        {
+            _posterEngines ??= CoreUtils.TypeList(
+                AppDomain.CurrentDomain.GetAssemblies(),
+                x => x.IsClass
+                    && !x.IsAbstract
+                    && x.GetTypeInfo().GenericTypeParameters.Length == 1
+                    && x.HasInterface(typeof(IPosterEngine<,,>))
+            ).Select(x => new EngineType
+            {
+                Engine = x,
+                Entity = x.GetInterfaceDefinition(typeof(IPosterEngine<,,>))!.GenericTypeArguments[0],
+                Poster = x.GetInterfaceDefinition(typeof(IPosterEngine<,,>))!.GenericTypeArguments[1].GetGenericTypeDefinition()
+            }).ToArray();
+            return _posterEngines;
+        }
+
         /// <summary>
         /// Get the <see cref="IPosterEngine{TPostable,TPoster,TSettings}"/> for <typeparamref name="T"/>
         /// based on the current <see cref="PostableSettings"/> for <typeparamref name="T"/>.
@@ -193,6 +195,58 @@ namespace InABox.Core
             return (Activator.CreateInstance(engine) as IPosterEngine<T>)!;
         }
 
+        #endregion
+
+        #region Auto-Refresh
+
+        /// <summary>
+        /// Check if <paramref name="item"/> needs to be reposted; if it does, <see cref="IPostable.PostedStatus"/> will be set to
+        /// <see cref="PostedStatus.RequiresRepost"/> once this function is finished.
+        /// </summary>
+        /// <remarks>
+        /// This will only do something if the currently set poster for this type has the <see cref="IAutoRefreshPoster{TEntity}"/> interface.
+        /// </remarks>
+        /// <typeparam name="T"></typeparam>
+        /// <returns><see langword="true"/> if the item's status has been updated and needs to be reposted.</returns>
+        public static bool CheckPostedStatus<T>(PostableSettings settings, T item)
+            where T : BaseObject
+        {
+            if (!(item is IPostable postable))
+            {
+                return false;
+            }
+            if (postable.PostedStatus != PostedStatus.Posted || item?.HasOriginalValue(nameof(IPostable.PostedStatus)) == true)
+            {
+                return false;
+            }
+
+            settings = FixPostableSettings(typeof(T), settings);
+            if (settings.PosterType.IsNullOrWhiteSpace())
+            {
+                return false;
+            }
+            var poster = GetPosters()?.FirstOrDefault(x => x.EntityName() == settings.PosterType);
+            if (poster is null)
+            {
+                return false;
+            }
+            var iautoRefresh = poster.GetInterfaceDefinition(typeof(IAutoRefreshPoster<,>));
+            if(iautoRefresh != null)
+            {
+                var autoRefresher = Activator.CreateInstance(iautoRefresh.GenericTypeArguments[1]) as IAutoRefresher<T>;
+                if (autoRefresher != null && autoRefresher.ShouldRepost(item))
+                {
+                    postable.PostedStatus = PostedStatus.RequiresRepost;
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        #endregion
+
+        #region Process
+
         /// <summary>
         /// Process <paramref name="model"/> with the currently set <see cref="IPosterEngine{TPostable, TPoster, TSettings}"/>
         /// for <typeparamref name="T"/>.
@@ -210,5 +264,7 @@ namespace InABox.Core
         {
             return CreateEngine<T>().Process(model);
         }
+
+        #endregion
     }
 }

+ 5 - 1
InABox.Database/Stores/Store.cs

@@ -1,6 +1,7 @@
 using System.Collections.Concurrent;
 using System.Reflection;
 using System.Text.RegularExpressions;
+using InABox.Configuration;
 using InABox.Core;
 using NPOI.POIFS.FileSystem;
 
@@ -381,7 +382,10 @@ namespace InABox.Database
 
         protected virtual void BeforeSave(T entity)
         {
-
+            if(entity is IPostable)
+            {
+                PosterUtils.CheckPostedStatus(new GlobalConfiguration<PostableSettings>(typeof(T).Name, new DbConfigurationProvider<GlobalSettings>(UserID)).Load(), entity);
+            }
 
             // Check for (a) blank code fields and (b) duplicate codes
             // There may be more than one code on an entity (why would you do this?)