diff --git a/.gitignore b/.gitignore index 08f8524d8..1e36f3ee4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ packages/ plugin-all/ plugin-samples/ .config/ +src/SSCMS.Web/log/ +src/SSCMS.Web/logs/ src/SSCMS.Web/plugins/ src/SSCMS.Web/.vs/ src/SSCMS.Web/.vscode/ @@ -17,6 +19,7 @@ src/SSCMS.Web/.config/ src/SSCMS.Web/version.txt sscms-all.sln +*.ps1 *.zip *.sql *.exe diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..4f06800aa --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build +WORKDIR /sscms +COPY . . +RUN apt-get update -yq \ + && apt-get install curl gnupg -yq \ + && curl -sL https://deb.nodesource.com/setup_12.x | bash \ + && apt-get install nodejs -yq +RUN npm install +RUN npm run build-linux-x64 +RUN dotnet build ./build-linux-x64/build.sln -c Release + +FROM build AS publish +RUN dotnet publish ./build-linux-x64/src/SSCMS.Cli/SSCMS.Cli.csproj -c Release -o ./publish/sscms-linux-x64 +RUN dotnet publish ./build-linux-x64/src/SSCMS.Web/SSCMS.Web.csproj -c Release -o ./publish/sscms-linux-x64 +RUN npm run copy-linux-x64 + +FROM base AS final +WORKDIR /app +COPY --from=publish /sscms/publish/sscms-linux-x64 . +ENTRYPOINT ["dotnet", "SSCMS.Web.dll"] \ No newline at end of file diff --git a/README.md b/README.md index b5965a71a..e5dd63c57 100644 --- a/README.md +++ b/README.md @@ -64,37 +64,73 @@ SSCMS 基于 .NET Core,能够以最低的成本、最少的人力投入在最 ```code │ sscms.sln Visual Studio 项目文件 │ -├─src/SS.CMS.Abstractions 接口、基础类 -├─src/SS.CMS CMS核心代码 +├─src/SS.CMS 接口、基础类 ├─src/SS.CMS.Cli 命令行工具 -├─src/SS.CMS.Web .NET CORE 控制器 -└─tests 测试库 +├─src/SS.CMS.Core CMS核心代码 +├─src/SS.CMS.Web CMS App +└─tests 测试 ``` ## 发布跨平台版本 -Window(64 位): +### Window(64 位): ``` -dotnet publish ./src/SSCMS/SSCMS.csproj -r win-x64 --configuration Release -o dist/sscms-win-x64 /p:PublishSingleFile=true +npm install +npm run build-win-x64 +dotnet build ./build-win-x64/build.sln -c Release +dotnet publish ./build-win-x64/src/SSCMS.Cli/SSCMS.Cli.csproj -r win-x64 -c Release -o ./publish/sscms-win-x64 /p:PublishTrimmed=true +dotnet publish ./build-win-x64/src/SSCMS.Web/SSCMS.Web.csproj -r win-x64 -c Release -o ./publish/sscms-win-x64 /p:PublishTrimmed=true +npm run copy-win-x64 ``` -Window(32 位): +> Note: 进入文件夹 `./publish/sscms-win-x64` 获取最终发布版本 + +### Window(32 位): ``` -dotnet publish ./src/SSCMS/SSCMS.csproj -r win-x86 --configuration Release -o dist/sscms-win-x86 /p:PublishSingleFile=true +npm install +npm run build-win-x32 +dotnet build ./build-win-x32/build.sln -c Release +dotnet publish ./build-win-x32/src/SSCMS.Cli/SSCMS.Cli.csproj -r win-x32 -c Release -o ./publish/sscms-win-x32 /p:PublishTrimmed=true +dotnet publish ./build-win-x32/src/SSCMS.Web/SSCMS.Web.csproj -r win-x32 -c Release -o ./publish/sscms-win-x32 /p:PublishTrimmed=true +npm run copy-win-x32 ``` -Linux: +> Note: 进入文件夹 `./publish/sscms-win-x32` 获取最终发布版本 + +### Linux: ``` -dotnet publish ./src/SSCMS/SSCMS.csproj -r linux-x64 --configuration Release -o dist/sscms-linux-x64 /p:PublishSingleFile=true +npm install +npm run build-linux-x64 +dotnet build ./build-linux-x64/build.sln -c Release +dotnet publish ./build-linux-x64/src/SSCMS.Cli/SSCMS.Cli.csproj -r linux-x64 -c Release -o ./publish/sscms-linux-x64 /p:PublishTrimmed=true +dotnet publish ./build-linux-x64/src/SSCMS.Web/SSCMS.Web.csproj -r linux-x64 -c Release -o ./publish/sscms-linux-x64 /p:PublishTrimmed=true +npm run copy-linux-x64 ``` -MacOS: +> Note: 进入文件夹 `./publish/sscms-linux-x64` 获取最终发布版本 +### MacOS: + +``` +npm install +npm run build-osx-x64 +dotnet build ./build-osx-x64/build.sln -c Release +dotnet publish ./build-osx-x64/src/SSCMS.Cli/SSCMS.Cli.csproj -r osx-x64 -c Release -o ./publish/sscms-osx-x64 /p:PublishTrimmed=true +dotnet publish ./build-osx-x64/src/SSCMS.Web/SSCMS.Web.csproj -r osx-x64 -c Release -o ./publish/sscms-osx-x64 /p:PublishTrimmed=true +npm run copy-osx-x64 ``` -dotnet publish ./src/SSCMS/SSCMS.csproj -r osx-x64 --configuration Release -o dist/sscms-osx-x64 /p:PublishSingleFile=true + +> Note: 进入文件夹 `./publish/sscms-osx-x64` 获取最终发布版本 + +## 在 Docker 中运行 + +### 运行最新版本 +```sh +docker pull sscms/core:latest +docker run -it --rm -p 5000:80 --name sscms sscms/core:latest ``` ## 贡献代码 diff --git a/azure-pipelines.yml b/azure-pipelines.yml index fbbe1d0a1..3d800010f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,7 +9,7 @@ trigger: variables: netCoreSdkVersion: '3.1.201' buildConfiguration: 'Release' - productVersion: '7.0.0-preview7' + productVersion: '7.0.0' jobs: @@ -26,7 +26,8 @@ jobs: - script: npm install - script: npm run build-osx-x64 - script: dotnet build ./build-osx-x64/build.sln -c $(buildConfiguration) - - script: dotnet publish ./build-osx-x64/src/SSCMS.Web/SSCMS.Web.csproj -r osx-x64 -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-osx-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true + - script: dotnet publish ./build-osx-x64/src/SSCMS.Cli/SSCMS.Cli.csproj -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-osx-x64 + - script: dotnet publish ./build-osx-x64/src/SSCMS.Web/SSCMS.Web.csproj -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-osx-x64 - script: npm run copy-osx-x64 - task: ArchiveFiles@2 inputs: @@ -52,7 +53,8 @@ jobs: - script: npm install - script: npm run build-linux-x64 - script: dotnet build ./build-linux-x64/build.sln -c $(buildConfiguration) - - script: dotnet publish ./build-linux-x64/src/SSCMS.Web/SSCMS.Web.csproj -r linux-x64 -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-linux-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true + - script: dotnet publish ./build-linux-x64/src/SSCMS.Cli/SSCMS.Cli.csproj -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-linux-x64 + - script: dotnet publish ./build-linux-x64/src/SSCMS.Web/SSCMS.Web.csproj -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-linux-x64 - script: npm run copy-linux-x64 - task: ArchiveFiles@2 inputs: @@ -84,7 +86,8 @@ jobs: restoreSolution: './build-win-x64/build.sln' feedsToUse: 'select' - script: dotnet build ./build-win-x64/build.sln -c $(buildConfiguration) - - script: dotnet publish ./build-win-x64/src/SSCMS.Web/SSCMS.Web.csproj -r win-x64 -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-win-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true + - script: dotnet publish ./build-win-x64/src/SSCMS.Cli/SSCMS.Cli.csproj -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-win-x64 + - script: dotnet publish ./build-win-x64/src/SSCMS.Web/SSCMS.Web.csproj -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-win-x64 - script: npm run copy-win-x64 - script: npm run build-win-x86 @@ -94,7 +97,8 @@ jobs: restoreSolution: './build-win-x86/build.sln' feedsToUse: 'select' - script: dotnet build ./build-win-x86/build.sln -c $(buildConfiguration) - - script: dotnet publish ./build-win-x86/src/SSCMS.Web/SSCMS.Web.csproj -r win-x86 -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-win-x86 /p:PublishSingleFile=true /p:PublishTrimmed=true + - script: dotnet publish ./build-win-x86/src/SSCMS.Cli/SSCMS.Cli.csproj -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-win-x86 + - script: dotnet publish ./build-win-x86/src/SSCMS.Web/SSCMS.Web.csproj -c $(buildConfiguration) -o ./publish/sscms-$(productVersion)-win-x86 - script: npm run copy-win-x86 - task: ArchiveFiles@2 diff --git a/gulpfile.js b/gulpfile.js index 1285edc23..3f18028e8 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -11,7 +11,7 @@ const runSequence = require('gulp4-run-sequence'); var os = ''; -const version = process.env.PRODUCTVERSION; +const version = process.env.PRODUCTVERSION ? (process.env.PRODUCTVERSION + '-') : ''; const timestamp = (new Date()).getTime(); let publishDir = ''; let htmlDict = {}; @@ -72,12 +72,6 @@ gulp.task("build-src", function () { return gulp.src("./src/**/*").pipe(gulp.dest(`./build-${os}/src`)); }); -gulp.task("build-os", function () { - return gulp.src("./src/SSCMS/Utils/Constants.cs") - .pipe(replace('OperatingSystem = "win-x64";', `OperatingSystem = "${os}";`)) - .pipe(gulp.dest(`./build-${os}/src/SSCMS/Utils`)); -}); - gulp.task("build-sln", function () { return gulp.src("./build.sln").pipe(gulp.dest(`./build-${os}`)); }); @@ -139,10 +133,9 @@ gulp.task('build-clean', function(){ gulp.task("build-osx-x64", async function () { os = 'osx-x64'; - console.log("build version: " + version + "-" + os); + console.log("build version: " + version + os); return runSequence( "build-src", - "build-os", "build-sln", "build-ss-admin", "build-home", @@ -152,10 +145,9 @@ gulp.task("build-osx-x64", async function () { gulp.task("build-linux-x64", async function () { os = 'linux-x64'; - console.log("build version: " + version + "-" + os); + console.log("build version: " + version + os); return runSequence( "build-src", - "build-os", "build-sln", "build-ss-admin", "build-home", @@ -165,10 +157,9 @@ gulp.task("build-linux-x64", async function () { gulp.task("build-win-x64", async function () { os = 'win-x64'; - console.log("build version: " + version + "-" + os); + console.log("build version: " + version + os); return runSequence( "build-src", - "build-os", "build-sln", "build-ss-admin", "build-home", @@ -178,10 +169,9 @@ gulp.task("build-win-x64", async function () { gulp.task("build-win-x86", async function () { os = 'win-x86'; - console.log("build version: " + version + "-" + os); + console.log("build version: " + version + os); return runSequence( "build-src", - "build-os", "build-sln", "build-ss-admin", "build-home", @@ -195,27 +185,28 @@ gulp.task("copy-files", async function () { fs.copySync('./appsettings.json', publishDir + '/appsettings.json'); fs.copySync('./sscms.json', publishDir + '/sscms.json'); fs.copySync('./web.config', publishDir + '/web.config'); - fs.copySync('./src/SSCMS.Web/assets', publishDir + '/wwwroot/sitefiles/assets'); fs.copySync('./404.html', publishDir + '/wwwroot/404.html'); fs.copySync('./favicon.ico', publishDir + '/wwwroot/favicon.ico'); fs.copySync('./index.html', publishDir + '/wwwroot/index.html'); + fs.removeSync(publishDir + '/appsettings.Development.json'); }); gulp.task("copy-sscms-linux", async function () { - fs.copySync(publishDir + '/SSCMS.Web', publishDir + '/sscms'); - fs.removeSync(publishDir + '/SSCMS.Web.pdb'); - fs.removeSync(publishDir + '/SSCMS.Web'); + fs.copySync(publishDir + '/SSCMS.Cli', publishDir + '/sscms'); + fs.removeSync(publishDir + '/SSCMS.Cli.pdb'); + fs.removeSync(publishDir + '/SSCMS.Cli'); + fs.removeSync(publishDir + '/web.config'); }); gulp.task("copy-sscms-win", async function () { - fs.copySync(publishDir + '/SSCMS.Web.exe', publishDir + '/sscms.exe'); - fs.removeSync(publishDir + '/SSCMS.Web.pdb'); - fs.removeSync(publishDir + '/SSCMS.Web.exe'); + fs.copySync(publishDir + '/SSCMS.Cli.exe', publishDir + '/sscms.exe'); + fs.removeSync(publishDir + '/SSCMS.Cli.pdb'); + fs.removeSync(publishDir + '/SSCMS.Cli.exe'); }); gulp.task("copy-css", function () { return gulp - .src(["./src/SSCMS.Web/assets/**/*.css"]) + .src(["./src/SSCMS.Web/wwwroot/sitefiles/**/*.css"]) .pipe( minifier({ minify: true, @@ -227,24 +218,24 @@ gulp.task("copy-css", function () { ignoreFiles: ['.min.css'] }) ) - .pipe(gulp.dest(publishDir + "/wwwroot/sitefiles/assets")); + .pipe(gulp.dest(publishDir + "/wwwroot/sitefiles")); }); gulp.task("copy-js", function () { const f = filter(['**/*-min.js']); return gulp - .src(["./src/SSCMS.Web/assets/**/*.js"]) + .src(["./src/SSCMS.Web/wwwroot/sitefiles/**/*.js"]) .pipe(minify()) .pipe(f) .pipe(rename(function (path) { path.basename = path.basename.substring(0, path.basename.length - 4); })) - .pipe(gulp.dest(publishDir + "/wwwroot/sitefiles/assets")); + .pipe(gulp.dest(publishDir + "/wwwroot/sitefiles")); }); gulp.task("copy-osx-x64", async function (callback) { os = 'osx-x64'; - publishDir = './publish/sscms-' + version + '-' + os; + publishDir = './publish/sscms-' + version + os; console.log("publish dir: " + publishDir); return runSequence( @@ -257,7 +248,7 @@ gulp.task("copy-osx-x64", async function (callback) { gulp.task("copy-linux-x64", async function (callback) { os = 'linux-x64'; - publishDir = './publish/sscms-' + version + '-' + os; + publishDir = './publish/sscms-' + version + os; console.log("publish dir: " + publishDir); return runSequence( @@ -270,7 +261,7 @@ gulp.task("copy-linux-x64", async function (callback) { gulp.task("copy-win-x64", async function (callback) { os = 'win-x64'; - publishDir = './publish/sscms-' + version + '-' + os; + publishDir = './publish/sscms-' + version + os; console.log("publish dir: " + publishDir); return runSequence( @@ -283,7 +274,7 @@ gulp.task("copy-win-x64", async function (callback) { gulp.task("copy-win-x86", async function (callback) { os = 'win-x86'; - publishDir = './publish/sscms-' + version + '-' + os; + publishDir = './publish/sscms-' + version + os; console.log("publish dir: " + publishDir); return runSequence( diff --git a/src/SSCMS.Cli/Abstractions/IApiService.cs b/src/SSCMS.Cli/Abstractions/IApiService.cs index c76201a66..ba388aa66 100644 --- a/src/SSCMS.Cli/Abstractions/IApiService.cs +++ b/src/SSCMS.Cli/Abstractions/IApiService.cs @@ -21,6 +21,6 @@ public interface IApiService (bool success, ApiService.PluginAndUser result, string failureMessage) PluginsShow(string pluginId); - (bool success, ApiService.GetReleasesResult result, string failureMessage) GetReleases(bool isNightly, string version, List pluginIds); + (bool success, ApiService.GetReleasesResult result, string failureMessage) GetReleases(string version, List pluginIds); } } diff --git a/src/SSCMS.Cli/Abstractions/IApplication.cs b/src/SSCMS.Cli/Abstractions/IApplication.cs new file mode 100644 index 000000000..53a9d4b92 --- /dev/null +++ b/src/SSCMS.Cli/Abstractions/IApplication.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using Quartz; + +namespace SSCMS.Cli.Abstractions +{ + public interface IApplication + { + Task RunAsync(string[] args); + + Task RunExecuteAsync(string commandName, string[] commandArgs, string[] commandExtras, + IJobExecutionContext jobContext); + } +} diff --git a/src/SSCMS.Cli/Abstractions/IDataRestoreService.cs b/src/SSCMS.Cli/Abstractions/IDataRestoreService.cs index 7add84eb5..66eab5b31 100644 --- a/src/SSCMS.Cli/Abstractions/IDataRestoreService.cs +++ b/src/SSCMS.Cli/Abstractions/IDataRestoreService.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; +using System.Collections.Generic; using System.Threading.Tasks; using SSCMS.Cli.Core; diff --git a/src/SSCMS.Cli/Abstractions/IJobService.cs b/src/SSCMS.Cli/Abstractions/IJobService.cs index f05d745c4..d413380af 100644 --- a/src/SSCMS.Cli/Abstractions/IJobService.cs +++ b/src/SSCMS.Cli/Abstractions/IJobService.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using SSCMS.Plugins; namespace SSCMS.Cli.Abstractions { @@ -6,6 +7,6 @@ public interface IJobService { string CommandName { get; } void PrintUsage(); - Task ExecuteAsync(IJobContext context); + Task ExecuteAsync(IPluginJobContext context); } } diff --git a/src/SSCMS.Cli/Application.cs b/src/SSCMS.Cli/Application.cs index 217fbb717..6a06a91c9 100644 --- a/src/SSCMS.Cli/Application.cs +++ b/src/SSCMS.Cli/Application.cs @@ -1,17 +1,20 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Mono.Options; using Quartz; using Quartz.Impl; +using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; using SSCMS.Services; using SSCMS.Utils; namespace SSCMS.Cli { - public class Application + public class Application : IApplication { private bool _isHelp; private string _repeat; @@ -22,15 +25,17 @@ public class Application public static string[] CommandExtras { get; private set; } private readonly ISettingsManager _settingsManager; + private readonly IPluginManager _pluginManager; - public Application(ISettingsManager settingsManager) + public Application(ISettingsManager settingsManager, IPluginManager pluginManager) { _settingsManager = settingsManager; + _pluginManager = pluginManager; _options = new OptionSet { { "r|repeat=", "schedule CRON expression", v => _repeat = v }, - { "h|help", "命令说明", + { "h|help", "Display help", v => _isHelp = v != null } }; } @@ -39,7 +44,7 @@ public async Task RunAsync(string[] args) { if (!CliUtils.ParseArgs(_options, args)) return; - var jobServiceCommandNames = CliUtils.GetJobServiceCommandNames(); + var jobServiceCommandNames = GetJobServiceCommandNames(); var isJobService = false; var commandName = string.Empty; @@ -77,6 +82,12 @@ public async Task RunAsync(string[] args) } } } + else + { + isJobService = true; + commandName = "status"; + } + CommandName = commandName; CommandArgs = commandArgs.ToArray(); CommandExtras = commandExtras.ToArray(); @@ -115,10 +126,10 @@ private async Task RunHelpAsync(string commandName) { if (_isHelp || string.IsNullOrEmpty(commandName)) { - await WriteUtils.PrintInfoAsync(_settingsManager); + await Console.Out.WriteLineAsync("Welcome to SSCMS Command Line"); await Console.Out.WriteLineAsync(); - var services = CliUtils.GetJobServices(); + var services = GetJobServices(); foreach (var service in services) { await WriteUtils.PrintRowLine(); @@ -130,7 +141,7 @@ private async Task RunHelpAsync(string commandName) } else { - Console.WriteLine($"'{commandName}' is not a sscms-cli command. See 'sscms-cli --help'"); + Console.WriteLine($"'{commandName}' is not a sscms command. See 'sscms --help'"); } } @@ -171,7 +182,7 @@ public async Task RunExecuteAsync(string commandName, string[] commandArgs, stri { try { - var service = CliUtils.GetJobService(commandName); + var service = GetJobService(commandName); if (service != null) { var context = new JobContext(commandName, commandArgs, commandExtras, jobContext); @@ -195,5 +206,25 @@ public async Task RunExecuteAsync(string commandName, string[] commandArgs, stri //}); } } + + private IJobService GetJobService(string commandName) + { + var provider = _settingsManager.BuildServiceProvider(); + var services = provider.GetServices(); + return services.FirstOrDefault(x => StringUtils.EqualsIgnoreCase(x.CommandName, commandName)); + } + + private List GetJobServiceCommandNames() + { + var provider = _settingsManager.BuildServiceProvider(); + var services = provider.GetServices(); + return services.Select(x => x.CommandName).ToList(); + } + + private IEnumerable GetJobServices() + { + var provider = _settingsManager.BuildServiceProvider(); + return provider.GetServices(); + } } } \ No newline at end of file diff --git a/src/SSCMS.Cli/Core/CliUtils.cs b/src/SSCMS.Cli/Core/CliUtils.cs index 1a3c85545..a29c3cfa8 100644 --- a/src/SSCMS.Cli/Core/CliUtils.cs +++ b/src/SSCMS.Cli/Core/CliUtils.cs @@ -1,10 +1,8 @@ using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using Mono.Options; -using SSCMS.Cli.Abstractions; +using SSCMS.Configuration; using SSCMS.Services; using SSCMS.Utils; @@ -12,34 +10,6 @@ namespace SSCMS.Cli.Core { public static class CliUtils { - private static ServiceProvider Provider { get; set; } - public static void SetProvider(ServiceProvider provider) - { - Provider = provider; - } - - public static Application GetApplication() - { - return Provider.GetRequiredService(); - } - - public static IJobService GetJobService(string commandName) - { - var services = Provider.GetServices(); - return services.FirstOrDefault(x => StringUtils.EqualsIgnoreCase(x.CommandName, commandName)); - } - - public static List GetJobServiceCommandNames() - { - var services = Provider.GetServices(); - return services.Select(x => x.CommandName).ToList(); - } - - public static IEnumerable GetJobServices() - { - return Provider.GetServices(); - } - // https://stackoverflow.com/questions/491595/best-way-to-parse-command-line-arguments-in-c public static bool ParseArgs(OptionSet options, string[] args) { @@ -100,17 +70,14 @@ public static async Task AppendErrorLogAsync(string filePath, TextLogInfo log) await FileUtils.AppendTextAsync(filePath, Encoding.UTF8, builder.ToString()); } - public static string GetWebConfigPath(string configFile, ISettingsManager settingsManager) + public static string GetConfigPath(ISettingsManager settingsManager) { - return PathUtils.IsFilePath(configFile) - ? configFile - : PathUtils.Combine(settingsManager.ContentRootPath, - !string.IsNullOrEmpty(configFile) ? configFile : Constants.ConfigFileName); + return PathUtils.Combine(settingsManager.ContentRootPath, Constants.ConfigFileName); } public static bool IsSsCmsExists(string directoryPath) { - return FileUtils.IsFileExists(PathUtils.Combine(directoryPath, Constants.ConfigFileName)) && FileUtils.IsFileExists(PathUtils.Combine(directoryPath, "appsettings.json")) && DirectoryUtils.IsDirectoryExists("wwwroot"); + return FileUtils.IsFileExists(PathUtils.Combine(directoryPath, Constants.ConfigFileName)) && FileUtils.IsFileExists(PathUtils.Combine(directoryPath, "appsettings.json")) && DirectoryUtils.IsDirectoryExists(Constants.WwwrootDirectory); } public static string GetOsUserConfigFilePath() diff --git a/src/SSCMS.Cli/Core/JobContext.cs b/src/SSCMS.Cli/Core/JobContext.cs index 68cdc5310..38230ea79 100644 --- a/src/SSCMS.Cli/Core/JobContext.cs +++ b/src/SSCMS.Cli/Core/JobContext.cs @@ -1,9 +1,10 @@ using System; using Quartz; +using SSCMS.Plugins; namespace SSCMS.Cli.Core { - public class JobContext : IJobContext + public class JobContext : IPluginJobContext { public JobContext(string command, string[] args, string[] extras, IJobExecutionContext context) { diff --git a/src/SSCMS.Cli/Core/SchedulerJob.cs b/src/SSCMS.Cli/Core/SchedulerJob.cs index 9069c1429..13596b436 100644 --- a/src/SSCMS.Cli/Core/SchedulerJob.cs +++ b/src/SSCMS.Cli/Core/SchedulerJob.cs @@ -8,8 +8,7 @@ internal class SchedulerJob : IJob { public async Task Execute(IJobExecutionContext context) { - var application = CliUtils.GetApplication(); - await application.RunExecuteAsync(Application.CommandName, Application.CommandArgs, Application.CommandExtras, context); + await Program.Application.RunExecuteAsync(Application.CommandName, Application.CommandArgs, Application.CommandExtras, context); if (context.NextFireTimeUtc != null) { diff --git a/src/SSCMS.Cli/Core/TextLogInfo.cs b/src/SSCMS.Cli/Core/TextLogInfo.cs index a65b4e78c..4798a5720 100644 --- a/src/SSCMS.Cli/Core/TextLogInfo.cs +++ b/src/SSCMS.Cli/Core/TextLogInfo.cs @@ -1,5 +1,4 @@ using System; -using SSCMS; using SSCMS.Utils; namespace SSCMS.Cli.Core diff --git a/src/SSCMS.Cli/Core/TreeInfo.cs b/src/SSCMS.Cli/Core/TreeInfo.cs index d01574d22..6f6ad2f14 100644 --- a/src/SSCMS.Cli/Core/TreeInfo.cs +++ b/src/SSCMS.Cli/Core/TreeInfo.cs @@ -1,5 +1,4 @@ -using SSCMS; -using SSCMS.Services; +using SSCMS.Services; using SSCMS.Utils; namespace SSCMS.Cli.Core diff --git a/src/SSCMS.Cli/Core/WriteUtils.cs b/src/SSCMS.Cli/Core/WriteUtils.cs index 6fec304d8..ef2070abd 100644 --- a/src/SSCMS.Cli/Core/WriteUtils.cs +++ b/src/SSCMS.Cli/Core/WriteUtils.cs @@ -1,10 +1,6 @@ using System; -using System.Reflection; +using System.Linq; using System.Threading.Tasks; -using Datory; -using SSCMS.Cli.Models; -using SSCMS.Services; -using SSCMS.Utils; namespace SSCMS.Cli.Core { @@ -13,43 +9,23 @@ public static class WriteUtils public static async Task PrintSuccessAsync(string successMessage) { var backgroundColor = Console.BackgroundColor; - //var foregroundColor = Console.ForegroundColor; Console.BackgroundColor = ConsoleColor.DarkGreen; - //Console.ForegroundColor = ConsoleColor.Black; await Console.Out.WriteAsync(" SUCCESS "); Console.BackgroundColor = backgroundColor; - //Console.ForegroundColor = foregroundColor; await Console.Out.WriteAsync($" {successMessage}"); + await Console.Out.WriteLineAsync(); } public static async Task PrintErrorAsync(string errorMessage) { var backgroundColor = Console.BackgroundColor; - //var foregroundColor = Console.ForegroundColor; Console.BackgroundColor = ConsoleColor.DarkRed; - //Console.ForegroundColor = ConsoleColor.Black; await Console.Out.WriteAsync(" ERROR "); Console.BackgroundColor = backgroundColor; - //Console.ForegroundColor = foregroundColor; await Console.Out.WriteAsync($" {errorMessage}"); - } - - public static async Task PrintInfoAsync(ISettingsManager settingsManager) - { - await Console.Out.WriteLineAsync($"Cli version: {settingsManager.Version}"); - var entryAssembly = Assembly.GetExecutingAssembly(); - await Console.Out.WriteLineAsync($"Cli location: {entryAssembly.Location}"); - await Console.Out.WriteLineAsync($"Work location: {settingsManager.ContentRootPath}"); - - var configPath = PathUtils.Combine(settingsManager.ContentRootPath, Constants.ConfigFileName); - - if (FileUtils.IsFileExists(configPath)) - { - await Console.Out.WriteLineAsync($"Database type: {settingsManager.Database.DatabaseType.GetDisplayName()}"); - await Console.Out.WriteLineAsync($"Database connection string: {settingsManager.DatabaseConnectionString}"); - } + await Console.Out.WriteLineAsync(); } public static async Task PrintRowLineAsync() @@ -59,13 +35,8 @@ public static async Task PrintRowLineAsync() public static async Task PrintRowAsync(params string[] columns) { - int width = (CliConstants.ConsoleTableWidth - columns.Length) / columns.Length; - string row = "|"; - - foreach (string column in columns) - { - row += AlignCentre(column, width) + "|"; - } + var width = (CliConstants.ConsoleTableWidth - columns.Length) / columns.Length; + var row = columns.Aggregate("|", (current, column) => current + AlignCentre(column, width) + "|"); await Console.Out.WriteLineAsync(row); } @@ -86,13 +57,8 @@ private static string AlignCentre(string text, int width) public static async Task PrintRow(params string[] columns) { - int width = (CliConstants.ConsoleTableWidth - columns.Length) / columns.Length; - string row = "|"; - - foreach (string column in columns) - { - row += AlignCentre(column, width) + "|"; - } + var width = (CliConstants.ConsoleTableWidth - columns.Length) / columns.Length; + var row = columns.Aggregate("|", (current, column) => current + AlignCentre(column, width) + "|"); await Console.Out.WriteLineAsync(row); } diff --git a/src/SSCMS.Cli/Extensions/ServiceCollectionExtensions.cs b/src/SSCMS.Cli/Extensions/ServiceCollectionExtensions.cs index 71344f5f1..7b882004d 100644 --- a/src/SSCMS.Cli/Extensions/ServiceCollectionExtensions.cs +++ b/src/SSCMS.Cli/Extensions/ServiceCollectionExtensions.cs @@ -22,7 +22,7 @@ public static void AddCliJobs(this IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/src/SSCMS.Cli/Jobs/DataBackupJob.cs b/src/SSCMS.Cli/Jobs/DataBackupJob.cs index dcdda6c45..4a82754d5 100644 --- a/src/SSCMS.Cli/Jobs/DataBackupJob.cs +++ b/src/SSCMS.Cli/Jobs/DataBackupJob.cs @@ -5,6 +5,7 @@ using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Plugins; using SSCMS.Services; using SSCMS.Utils; @@ -14,8 +15,9 @@ public class DataBackupJob : IJobService { public string CommandName => "data backup"; + private string _databaseType; + private string _connectionString; private string _directory; - private string _configFile; private List _includes; private List _excludes; private int _maxRows; @@ -31,31 +33,47 @@ public DataBackupJob(ISettingsManager settingsManager, IDatabaseManager database _databaseManager = databaseManager; _options = new OptionSet { - { "d|directory=", "指定保存备份文件的文件夹名称", - v => _directory = v }, - { "c|config-file=", "指定配置文件Web.config路径或文件名", - v => _configFile = v }, - { "includes=", "指定需要备份的表,多个表用英文逗号隔开,默认备份所有表", - v => _includes = v == null ? null : ListUtils.GetStringList(v) }, - { "excludes=", "指定需要排除的表,多个表用英文逗号隔开", - v => _excludes = v == null ? null : ListUtils.GetStringList(v) }, - { "max-rows=", "指定需要备份的表的最大行数", - v => _maxRows = v == null ? 0 : TranslateUtils.ToInt(v) }, - { "h|help", "命令说明", - v => _isHelp = v != null } + { + "t|database-type=", "Database type", + v => _databaseType = v + }, + { + "c|connection-string=", "Database connection string", + v => _connectionString = v + }, + { + "d|directory=", "Backup folder name", + v => _directory = v + }, + { + "includes=", "Include table names, separated by commas, default backup all tables", + v => _includes = v == null ? null : ListUtils.GetStringList(v) + }, + { + "excludes=", "Exclude table names, separated by commas", + v => _excludes = v == null ? null : ListUtils.GetStringList(v) + }, + { + "max-rows=", "Maximum number of rows to backup. All data is backed up by default", + v => _maxRows = v == null ? 0 : TranslateUtils.ToInt(v) + }, + { + "h|help", "Display help", + v => _isHelp = v != null + } }; } public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); - Console.WriteLine("Summary: backup database to dist"); + Console.WriteLine($"Usage: sscms {CommandName}"); + Console.WriteLine("Summary: backup database to folder"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -74,13 +92,28 @@ public async Task ExecuteAsync(IJobContext context) var treeInfo = new TreeInfo(_settingsManager, directory); DirectoryUtils.CreateDirectoryIfNotExists(treeInfo.DirectoryPath); - var webConfigPath = CliUtils.GetWebConfigPath(_configFile, _settingsManager); - if (!FileUtils.IsFileExists(webConfigPath)) + var configPath = CliUtils.GetConfigPath(_settingsManager); + + var databaseType = TranslateUtils.ToEnum(_databaseType, DatabaseType.MySql); + var connectionString = _connectionString; + if (string.IsNullOrEmpty(connectionString)) { - await WriteUtils.PrintErrorAsync($"系统配置文件不存在:{webConfigPath}!"); - return; + if (FileUtils.IsFileExists(configPath)) + { + databaseType = _settingsManager.Database.DatabaseType; + connectionString = _settingsManager.DatabaseConnectionString; + } + else + { + await WriteUtils.PrintErrorAsync($"The sscms.json file does not exist: {configPath}"); + return; + } } + await Console.Out.WriteLineAsync($"Database type: {databaseType.GetDisplayName()}"); + await Console.Out.WriteLineAsync($"Database connection string: {connectionString}"); + await Console.Out.WriteLineAsync($"Backup folder: {treeInfo.DirectoryPath}"); + //WebConfigUtils.Load(_settingsManager.ContentRootPath, webConfigPath); //if (string.IsNullOrEmpty(WebConfigUtils.ConnectionString)) @@ -100,6 +133,14 @@ public async Task ExecuteAsync(IJobContext context) // return; //} + var database = new Database(databaseType, connectionString); + var (isConnectionWorks, errorMessage) = await database.IsConnectionWorksAsync(); + if (!isConnectionWorks) + { + await WriteUtils.PrintErrorAsync($"Unable to connect to database, error message:{errorMessage}"); + return; + } + if (_excludes == null) { _excludes = new List(); @@ -110,15 +151,15 @@ public async Task ExecuteAsync(IJobContext context) _excludes.Add("siteserver_Log"); _excludes.Add("siteserver_Tracking"); - await Backup(_settingsManager, _databaseManager, _includes, _excludes, _maxRows, treeInfo); + await Backup(database, _databaseManager, _includes, _excludes, _maxRows, treeInfo); await WriteUtils.PrintRowLineAsync(); - await WriteUtils.PrintSuccessAsync($"恭喜,成功备份数据库至文件夹:{treeInfo.DirectoryPath}!"); + await WriteUtils.PrintSuccessAsync("backup database to folder successfully!"); } - public static async Task Backup(ISettingsManager settingsManager, IDatabaseManager databaseManager, List includes, List excludes, int maxRows, TreeInfo treeInfo) + public static async Task Backup(IDatabase database, IDatabaseManager databaseManager, List includes, List excludes, int maxRows, TreeInfo treeInfo) { - var allTableNames = await settingsManager.Database.GetTableNamesAsync(); + var allTableNames = await database.GetTableNamesAsync(); var tableNames = new List(); @@ -133,12 +174,14 @@ public static async Task Backup(ISettingsManager settingsManager, IDatabaseManag await FileUtils.WriteTextAsync(treeInfo.TablesFilePath, TranslateUtils.JsonSerialize(tableNames)); await WriteUtils.PrintRowLineAsync(); - await WriteUtils.PrintRowAsync("备份表名称", "总条数"); + await WriteUtils.PrintRowAsync("Backup table name", "Count"); await WriteUtils.PrintRowLineAsync(); foreach (var tableName in tableNames) { - var repository = new Repository(settingsManager.Database, tableName); + var columns = await database.GetTableColumnsAsync(tableName); + var repository = new Repository(database, tableName, columns); + var tableInfo = new TableInfo { Columns = repository.TableColumns, @@ -153,7 +196,7 @@ public static async Task Backup(ISettingsManager settingsManager, IDatabaseManag await WriteUtils.PrintRowAsync(tableName, tableInfo.TotalCount.ToString("#,0")); - var identityColumnName = await settingsManager.Database.AddIdentityColumnIdIfNotExistsAsync(tableName, tableInfo.Columns); + var identityColumnName = await database.AddIdentityColumnIdIfNotExistsAsync(tableName, tableInfo.Columns); if (tableInfo.TotalCount > 0) { diff --git a/src/SSCMS.Cli/Jobs/DataRestoreJob.cs b/src/SSCMS.Cli/Jobs/DataRestoreJob.cs index 4a1ae8b92..f6ad74b5d 100644 --- a/src/SSCMS.Cli/Jobs/DataRestoreJob.cs +++ b/src/SSCMS.Cli/Jobs/DataRestoreJob.cs @@ -1,9 +1,12 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Datory; using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Configuration; +using SSCMS.Plugins; using SSCMS.Repositories; using SSCMS.Services; using SSCMS.Utils; @@ -15,7 +18,6 @@ public class DataRestoreJob : IJobService public string CommandName => "data restore"; private string _directory; - private string _configFile; private List _includes; private List _excludes; private bool _dataOnly; @@ -35,31 +37,29 @@ public DataRestoreJob(ISettingsManager settingsManager, IConfigRepository config _restoreService = restoreService; _options = new OptionSet { - { "d|directory=", "从指定的文件夹中恢复数据", + { "d|directory=", "Restore folder name", v => _directory = v }, - { "c|config-file=", "指定配置文件Web.config路径或文件名", - v => _configFile = v }, - { "includes=", "指定需要还原的表,多个表用英文逗号隔开,默认还原所有表", + { "includes=", "Include table names, separated by commas, default restore all tables", v => _includes = v == null ? null : ListUtils.GetStringList(v) }, - { "excludes=", "指定需要排除的表,多个表用英文逗号隔开", + { "excludes=", "Exclude table names, separated by commas", v => _excludes = v == null ? null : ListUtils.GetStringList(v) }, - { "data-only", "仅恢复数据", + { "data-only", "Restore data only", v => _dataOnly = v != null }, - { "h|help", "命令说明", + { "h|help", "Display help", v => _isHelp = v != null } }; } public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: restore backup files to database"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -71,7 +71,7 @@ public async Task ExecuteAsync(IJobContext context) if (string.IsNullOrEmpty(_directory)) { - await WriteUtils.PrintErrorAsync("需要指定恢复数据的文件夹名称:directory"); + await WriteUtils.PrintErrorAsync("Restore folder name not specified: --directory"); return; } @@ -90,10 +90,10 @@ public async Task ExecuteAsync(IJobContext context) return; } - var webConfigPath = CliUtils.GetWebConfigPath(_configFile, _settingsManager); - if (!FileUtils.IsFileExists(webConfigPath)) + var configPath = CliUtils.GetConfigPath(_settingsManager); + if (!FileUtils.IsFileExists(configPath)) { - await WriteUtils.PrintErrorAsync($"系统配置文件不存在:{webConfigPath}!"); + await WriteUtils.PrintErrorAsync($"The sscms.json file does not exist: {configPath}"); return; } @@ -109,34 +109,49 @@ public async Task ExecuteAsync(IJobContext context) //await Console.Out.WriteLineAsync($"连接字符串: {WebConfigUtils.ConnectionString}"); //await Console.Out.WriteLineAsync($"恢复文件夹: {treeInfo.DirectoryPath}"); + await Console.Out.WriteLineAsync($"Database type: {_settingsManager.Database.DatabaseType.GetDisplayName()}"); + await Console.Out.WriteLineAsync($"Database connection string: {_settingsManager.Database.ConnectionString}"); + await Console.Out.WriteLineAsync($"Restore folder: {treeInfo.DirectoryPath}"); + var (isConnectionWorks, errorMessage) = await _settingsManager.Database.IsConnectionWorksAsync(); if (!isConnectionWorks) { - await WriteUtils.PrintErrorAsync($"数据库连接错误:{errorMessage}"); + await WriteUtils.PrintErrorAsync($"Unable to connect to database, error message:{errorMessage}"); return; } - if (!_dataOnly) - { - if (!await _configRepository.IsNeedInstallAsync()) - { - await WriteUtils.PrintErrorAsync("数据无法在已安装系统的数据库中恢复,命令执行失败"); - return; - } - - // 恢复前先创建表,确保系统在恢复的数据库中能够使用 - await _databaseManager.CreateSiteServerTablesAsync(); - } + //if (!_dataOnly) + //{ + // if (!await _configRepository.IsNeedInstallAsync()) + // { + // await WriteUtils.PrintErrorAsync("The data could not be restored on the installed sscms database"); + // return; + // } + + // // 恢复前先创建表,确保系统在恢复的数据库中能够使用 + // //await _databaseManager.CreateSiteServerTablesAsync(); + + // if (_settingsManager.DatabaseType == DatabaseType.SQLite) + // { + // var filePath = PathUtils.Combine(_settingsManager.ContentRootPath, Constants.DefaultLocalDbFileName); + // if (!FileUtils.IsFileExists(filePath)) + // { + // await FileUtils.WriteTextAsync(filePath, string.Empty); + // } + // } + + // await _databaseManager.SyncDatabaseAsync(); + //} await WriteUtils.PrintRowLineAsync(); - await WriteUtils.PrintRowAsync("恢复表名称", "总条数"); + await WriteUtils.PrintRowAsync("Restore table name", "Count"); await WriteUtils.PrintRowLineAsync(); var errorLogFilePath = CliUtils.CreateErrorLogFile(CommandName, _settingsManager); await _restoreService.RestoreAsync(_includes, _excludes, _dataOnly, tablesFilePath, treeInfo, errorLogFilePath); - await Console.Out.WriteLineAsync($"恭喜,成功从文件夹:{treeInfo.DirectoryPath} 恢复数据!"); + await Console.Out.WriteLineAsync($"恭喜,成功从文件夹:{treeInfo.DirectoryPath} 恢复数据!"); } } } diff --git a/src/SSCMS.Cli/Jobs/DataSyncJob.cs b/src/SSCMS.Cli/Jobs/DataSyncJob.cs index f02077b47..9dedfbd71 100644 --- a/src/SSCMS.Cli/Jobs/DataSyncJob.cs +++ b/src/SSCMS.Cli/Jobs/DataSyncJob.cs @@ -4,6 +4,7 @@ using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Plugins; using SSCMS.Services; using SSCMS.Utils; @@ -36,9 +37,9 @@ public DataSyncJob(ISettingsManager settingsManager, IDatabaseManager databaseMa { { "d|directory=", "指定保存备份文件的文件夹名称", v => _directory = v }, - { "from=", "指定需要备份的配置文件Web.config路径或文件名", + { "from=", "指定需要备份的配置文件sscms.json路径或文件名", v => _from = v }, - { "to=", "指定需要恢复的配置文件Web.config路径或文件名", + { "to=", "指定需要恢复的配置文件sscms.json路径或文件名", v => _to = v }, { "includes=", "指定需要备份的表,多个表用英文逗号隔开,默认备份所有表", v => _includes = v == null ? null : ListUtils.GetStringList(v) }, @@ -46,21 +47,21 @@ public DataSyncJob(ISettingsManager settingsManager, IDatabaseManager databaseMa v => _excludes = v == null ? null : ListUtils.GetStringList(v) }, { "max-rows=", "指定需要备份的表的最大行数", v => _maxRows = v == null ? 0 : TranslateUtils.ToInt(v) }, - { "h|help", "命令说明", + { "h|help", "Display help", v => _isHelp = v != null } }; } public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: sync backup files to database"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -79,10 +80,10 @@ public async Task ExecuteAsync(IJobContext context) var treeInfo = new TreeInfo(_settingsManager, directory); DirectoryUtils.CreateDirectoryIfNotExists(treeInfo.DirectoryPath); - var backupWebConfigPath = CliUtils.GetWebConfigPath(_from, _settingsManager); - if (!FileUtils.IsFileExists(backupWebConfigPath)) + var backupConfigPath = PathUtils.Combine(_settingsManager.ContentRootPath, _from); + if (!FileUtils.IsFileExists(backupConfigPath)) { - await WriteUtils.PrintErrorAsync($"系统配置文件不存在:{backupWebConfigPath}!"); + await WriteUtils.PrintErrorAsync($"The sscms configuration file does not exist: {backupConfigPath}"); return; } //WebConfigUtils.Load(_settingsManager.ContentRootPath, backupWebConfigPath); @@ -99,7 +100,7 @@ public async Task ExecuteAsync(IJobContext context) var (isConnectionWorks, errorMessage) = await _settingsManager.Database.IsConnectionWorksAsync(); if (!isConnectionWorks) { - await WriteUtils.PrintErrorAsync($"数据库连接错误:{errorMessage}"); + await WriteUtils.PrintErrorAsync($"Unable to connect to database, error message:{errorMessage}"); return; } @@ -115,12 +116,12 @@ public async Task ExecuteAsync(IJobContext context) var errorLogFilePath = CliUtils.CreateErrorLogFile(CommandName, _settingsManager); - await DataBackupJob.Backup(_settingsManager, _databaseManager, _includes, _excludes, _maxRows, treeInfo); + await DataBackupJob.Backup(_settingsManager.Database, _databaseManager, _includes, _excludes, _maxRows, treeInfo); - var restoreWebConfigPath = CliUtils.GetWebConfigPath(_to, _settingsManager); - if (!FileUtils.IsFileExists(restoreWebConfigPath)) + var restoreConfigPath = PathUtils.Combine(_settingsManager.ContentRootPath, _to); + if (!FileUtils.IsFileExists(restoreConfigPath)) { - await WriteUtils.PrintErrorAsync($"系统配置文件不存在:{restoreWebConfigPath}!"); + await WriteUtils.PrintErrorAsync($"The sscms configuration file does not exist: {restoreConfigPath}"); return; } //WebConfigUtils.Load(_settingsManager.ContentRootPath, restoreWebConfigPath); @@ -134,14 +135,14 @@ public async Task ExecuteAsync(IJobContext context) (isConnectionWorks, errorMessage) = await _settingsManager.Database.IsConnectionWorksAsync(); if (!isConnectionWorks) { - await WriteUtils.PrintErrorAsync($"数据库连接错误:{errorMessage}"); + await WriteUtils.PrintErrorAsync($"Unable to connect to database, error message:{errorMessage}"); return; } await _restoreService.RestoreAsync(_includes, _excludes, true, treeInfo.DirectoryPath, treeInfo, errorLogFilePath); await WriteUtils.PrintRowLineAsync(); - await WriteUtils.PrintSuccessAsync("恭喜,成功同步数据!"); + await WriteUtils.PrintSuccessAsync("恭喜,成功同步数据!"); } } } diff --git a/src/SSCMS.Cli/Jobs/DataUpdateJob.cs b/src/SSCMS.Cli/Jobs/DataUpdateJob.cs index 0b367577c..c65851aed 100644 --- a/src/SSCMS.Cli/Jobs/DataUpdateJob.cs +++ b/src/SSCMS.Cli/Jobs/DataUpdateJob.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; -using System.Reflection; using System.Text; using System.Threading.Tasks; using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; using SSCMS.Cli.Updater; +using SSCMS.Plugins; using SSCMS.Services; using SSCMS.Utils; @@ -33,25 +33,25 @@ public DataUpdateJob(ISettingsManager settingsManager, IDatabaseManager database _updateService = updateService; _options = new OptionSet { - { "d|directory=", "指定需要升级至最新版本的备份数据文件夹", + { "d|directory=", "Backup folder name", v => _directory = v }, - { "content-split", "拆分内容表", + { "content-split", "Split content table by site", v => _contentSplit = v != null }, - { "h|help", "命令说明", + { "h|help", "Display help", v => _isHelp = v != null } }; } public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: update database to latest schema"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -63,7 +63,7 @@ public async Task ExecuteAsync(IJobContext context) if (string.IsNullOrEmpty(_directory)) { - await WriteUtils.PrintErrorAsync("未指定需要转换至最新版本的备份数据文件夹:directory"); + await WriteUtils.PrintErrorAsync("Backup folder name not specified: --directory"); return; } @@ -72,21 +72,20 @@ public async Task ExecuteAsync(IJobContext context) if (!DirectoryUtils.IsDirectoryExists(oldTreeInfo.DirectoryPath)) { - await WriteUtils.PrintErrorAsync($"备份数据的文件夹 {oldTreeInfo.DirectoryPath} 不存在"); + await WriteUtils.PrintErrorAsync($"The backup folder does not exist: {oldTreeInfo.DirectoryPath}"); return; } DirectoryUtils.CreateDirectoryIfNotExists(newTreeInfo.DirectoryPath); _updateService.Load(oldTreeInfo, newTreeInfo); - var version = Assembly.GetExecutingAssembly().GetName().Version.ToString(); - await Console.Out.WriteLineAsync($"备份数据文件夹: {oldTreeInfo.DirectoryPath},升级数据文件夹: {newTreeInfo.DirectoryPath},升级版本: {version.Substring(0, version.Length - 2)}"); + await Console.Out.WriteLineAsync($"Backup folder: {oldTreeInfo.DirectoryPath}, Update folder: {newTreeInfo.DirectoryPath}, Update to SSCMS version: {_settingsManager.Version}"); var oldTableNames = TranslateUtils.JsonDeserialize>(await FileUtils.ReadTextAsync(oldTreeInfo.TablesFilePath, Encoding.UTF8)); var newTableNames = new List(); await WriteUtils.PrintRowLineAsync(); - await WriteUtils.PrintRowAsync("备份表名称", "升级表名称", "总条数"); + await WriteUtils.PrintRowAsync("Backup table name", "Update table Name", "Count"); await WriteUtils.PrintRowLineAsync(); var siteIdList = new List(); @@ -173,7 +172,7 @@ await _updateService.UpdateSplitContentsTableInfoAsync(splitSiteTableDict, siteI await FileUtils.WriteTextAsync(newTreeInfo.TablesFilePath, TranslateUtils.JsonSerialize(newTableNames)); await WriteUtils.PrintRowLineAsync(); - await WriteUtils.PrintSuccessAsync($"恭喜,成功从备份文件夹:{oldTreeInfo.DirectoryPath} 升级至新版本:{newTreeInfo.DirectoryPath} !"); + await WriteUtils.PrintSuccessAsync("Update the backup data to the new version successfully!"); } } } diff --git a/src/SSCMS.Cli/Jobs/InstallDatabaseJob.cs b/src/SSCMS.Cli/Jobs/InstallDatabaseJob.cs new file mode 100644 index 000000000..80a211a69 --- /dev/null +++ b/src/SSCMS.Cli/Jobs/InstallDatabaseJob.cs @@ -0,0 +1,109 @@ +using System; +using System.Threading.Tasks; +using Datory; +using Mono.Options; +using SSCMS.Cli.Abstractions; +using SSCMS.Cli.Core; +using SSCMS.Configuration; +using SSCMS.Plugins; +using SSCMS.Repositories; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Cli.Jobs +{ + public class InstallDatabaseJob : IJobService + { + public string CommandName => "install database"; + + private string _userName; + private string _password; + private bool _isHelp; + + private readonly ISettingsManager _settingsManager; + private readonly IDatabaseManager _databaseManager; + private readonly IPathManager _pathManager; + private readonly IConfigRepository _configRepository; + private readonly IAdministratorRepository _administratorRepository; + private readonly OptionSet _options; + + public InstallDatabaseJob(ISettingsManager settingsManager, IDatabaseManager databaseManager, IPathManager pathManager, IConfigRepository configRepository, IAdministratorRepository administratorRepository) + { + _settingsManager = settingsManager; + _databaseManager = databaseManager; + _pathManager = pathManager; + _configRepository = configRepository; + _administratorRepository = administratorRepository; + + _options = new OptionSet { + { "u|userName", "Super administrator username", + v => _userName = v }, + { "p|password", "Super administrator username", + v => _password = v }, + { "h|help", "Display help", + v => _isHelp = v != null } + }; + } + + public void PrintUsage() + { + Console.WriteLine($"Usage: sscms {CommandName}"); + Console.WriteLine("Summary: install sscms"); + Console.WriteLine("Options:"); + _options.WriteOptionDescriptions(Console.Out); + Console.WriteLine(); + } + + public async Task ExecuteAsync(IPluginJobContext context) + { + if (!CliUtils.ParseArgs(_options, context.Args)) return; + + if (_isHelp) + { + PrintUsage(); + return; + } + + if (!await _configRepository.IsNeedInstallAsync()) + { + await WriteUtils.PrintErrorAsync($"SS CMS has been installed in {_settingsManager.ContentRootPath}"); + return; + } + + var userName = string.IsNullOrEmpty(_userName) + ? ReadUtils.GetString("Super administrator username:") + : _userName; + var password = string.IsNullOrEmpty(_password) + ? ReadUtils.GetPassword("Super administrator password:") + : _password; + + var (valid, message) = + await _administratorRepository.InsertValidateAsync(userName, password, string.Empty, string.Empty); + if (!valid) + { + await WriteUtils.PrintErrorAsync(message); + return; + } + + if (_settingsManager.DatabaseType == DatabaseType.SQLite) + { + var filePath = PathUtils.Combine(_settingsManager.ContentRootPath, Constants.DefaultLocalDbFileName); + if (!FileUtils.IsFileExists(filePath)) + { + await FileUtils.WriteTextAsync(filePath, string.Empty); + } + } + + (valid, message) = await _databaseManager.InstallAsync(userName, password, string.Empty, string.Empty); + if (!valid) + { + await WriteUtils.PrintErrorAsync(message); + return; + } + + await FileUtils.WriteTextAsync(_pathManager.GetRootPath("index.html"), Constants.Html5Empty); + + await WriteUtils.PrintSuccessAsync("Congratulations, SS CMS was installed successfully!"); + } + } +} diff --git a/src/SSCMS.Cli/Jobs/InstallDownloadJob.cs b/src/SSCMS.Cli/Jobs/InstallDownloadJob.cs index 103bad8bd..2334e73db 100644 --- a/src/SSCMS.Cli/Jobs/InstallDownloadJob.cs +++ b/src/SSCMS.Cli/Jobs/InstallDownloadJob.cs @@ -1,13 +1,14 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Datory; using Mono.Options; +using Semver; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; using SSCMS.Core.Plugins; using SSCMS.Core.Utils; +using SSCMS.Plugins; using SSCMS.Repositories; using SSCMS.Services; using SSCMS.Utils; @@ -18,7 +19,6 @@ public class InstallDownloadJob : IJobService { public string CommandName => "install download"; - private bool _isNightly; private bool _isHelp; private readonly IApiService _apiService; @@ -35,23 +35,21 @@ public InstallDownloadJob(IApiService apiService, ISettingsManager settingsManag _configRepository = configRepository; _options = new OptionSet { - { "nightly", "Install nightly version", - v => _isNightly = v != null }, - { "h|help", "命令说明", + { "h|help", "Display help", v => _isHelp = v != null } }; } public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: download sscms and save settings"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -63,40 +61,28 @@ public async Task ExecuteAsync(IJobContext context) var contentRootPath = _settingsManager.ContentRootPath; - var proceed = ReadUtils.GetYesNo($"Do you want to install SS CMS in {contentRootPath}?"); - if (!proceed) return; - - InstallUtils.Init(contentRootPath); - if (!CliUtils.IsSsCmsExists(contentRootPath)) { - var (success, result, errorMessage) = _apiService.GetReleases(_isNightly, string.Empty, null); + var (success, result, failureMessage) = _apiService.GetReleases(_settingsManager.Version, null); if (!success) { - await WriteUtils.PrintErrorAsync(errorMessage); + await WriteUtils.PrintErrorAsync(failureMessage); return; } - Console.WriteLine($"Downloading {result.Cms.Version}..."); - CloudUtils.Dl.DownloadCms(_pathManager, result.Cms.Version); + var proceed = ReadUtils.GetYesNo($"Do you want to install SS CMS in {contentRootPath}?"); + if (!proceed) return; - var name = CloudUtils.Dl.GetCmsDownloadName(result.Cms.Version); - var packagePath = _pathManager.GetPackagesPath(name); + Console.WriteLine($"Downloading SS CMS {result.Cms.Version}..."); + var directoryPath = CloudUtils.Dl.DownloadCms(_pathManager, _settingsManager.OSArchitecture, result.Cms.Version); - foreach (var fileName in DirectoryUtils.GetFileNames(packagePath).Where(fileName => - !StringUtils.EqualsIgnoreCase(fileName, $"{name}.zip") && - !StringUtils.EqualsIgnoreCase(fileName, Constants.ConfigFileName))) - { - FileUtils.CopyFile(PathUtils.Combine(packagePath, fileName), - PathUtils.Combine(contentRootPath, fileName), true); - } + await WriteUtils.PrintSuccessAsync($"{result.Cms.Version} download successfully!"); - foreach (var directoryName in DirectoryUtils.GetDirectoryNames(packagePath)) - { - DirectoryUtils.Copy(PathUtils.Combine(packagePath, directoryName), PathUtils.Combine(contentRootPath, directoryName), true); - } + DirectoryUtils.Copy(directoryPath, contentRootPath, true); } + InstallUtils.Init(contentRootPath); + if (!await _configRepository.IsNeedInstallAsync()) { await WriteUtils.PrintErrorAsync($"SS CMS has been installed in {contentRootPath}"); @@ -149,9 +135,10 @@ public async Task ExecuteAsync(IJobContext context) var databaseConnectionString = InstallUtils.GetDatabaseConnectionString(databaseType, databaseHost, isDatabaseDefaultPort, databasePort, databaseUserName, databasePassword, databaseName); var isProtectData = ReadUtils.GetYesNo("Protect settings in sscms.json?"); - _settingsManager.SaveSettings(_isNightly, isProtectData, databaseType, databaseConnectionString, string.Empty); + _settingsManager.SaveSettings(isProtectData, false, databaseType, databaseConnectionString, string.Empty, string.Empty, null, null); + + await WriteUtils.PrintSuccessAsync("SS CMS was download and ready for install, please run: sscms install database"); - await WriteUtils.PrintSuccessAsync("SS CMS was download and ready for install, please run sscms-cli install sscms"); } } } diff --git a/src/SSCMS.Cli/Jobs/InstallSsCmsJob.cs b/src/SSCMS.Cli/Jobs/InstallSsCmsJob.cs deleted file mode 100644 index 2c32cee27..000000000 --- a/src/SSCMS.Cli/Jobs/InstallSsCmsJob.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using System.Threading.Tasks; -using Datory; -using Mono.Options; -using SSCMS.Cli.Abstractions; -using SSCMS.Cli.Core; -using SSCMS.Repositories; -using SSCMS.Services; -using SSCMS.Utils; - -namespace SSCMS.Cli.Jobs -{ - public class InstallSsCmsJob : IJobService - { - public string CommandName => "install sscms"; - - private string _userName; - private string _password; - private bool _isHelp; - - private readonly ISettingsManager _settingsManager; - private readonly IDatabaseManager _databaseManager; - private readonly IPathManager _pathManager; - private readonly IOldPluginManager _pluginManager; - private readonly IConfigRepository _configRepository; - private readonly IAdministratorRepository _administratorRepository; - private readonly OptionSet _options; - - public InstallSsCmsJob(ISettingsManager settingsManager, IDatabaseManager databaseManager, IPathManager pathManager, IOldPluginManager pluginManager, IConfigRepository configRepository, IAdministratorRepository administratorRepository) - { - _settingsManager = settingsManager; - _databaseManager = databaseManager; - _pathManager = pathManager; - _pluginManager = pluginManager; - _configRepository = configRepository; - _administratorRepository = administratorRepository; - - _options = new OptionSet { - { "u|userName", "Super administrator username", - v => _userName = v }, - { "p|password", "Super administrator username", - v => _password = v }, - { "h|help", "命令说明", - v => _isHelp = v != null } - }; - } - - public void PrintUsage() - { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); - Console.WriteLine("Summary: install sscms"); - Console.WriteLine("Options:"); - _options.WriteOptionDescriptions(Console.Out); - Console.WriteLine(); - } - - public async Task ExecuteAsync(IJobContext context) - { - if (!CliUtils.ParseArgs(_options, context.Args)) return; - - if (_isHelp) - { - PrintUsage(); - return; - } - - if (!await _configRepository.IsNeedInstallAsync()) - { - await WriteUtils.PrintErrorAsync($"SS CMS has been installed in {_settingsManager.ContentRootPath}"); - return; - } - - var userName = string.IsNullOrEmpty(_userName) - ? ReadUtils.GetString("Super administrator username:") - : _userName; - var password = string.IsNullOrEmpty(_password) - ? ReadUtils.GetPassword("Super administrator password:") - : _password; - - var (valid, message) = - await _administratorRepository.InsertValidateAsync(userName, password, string.Empty, string.Empty); - if (!valid) - { - await WriteUtils.PrintErrorAsync(message); - return; - } - - if (_settingsManager.DatabaseType == DatabaseType.SQLite) - { - var filePath = PathUtils.Combine(_settingsManager.ContentRootPath, Constants.DefaultLocalDbFileName); - if (!FileUtils.IsFileExists(filePath)) - { - await FileUtils.WriteTextAsync(filePath, string.Empty); - } - } - - (valid, message) = await _databaseManager.InstallAsync(_pluginManager, userName, password, string.Empty, string.Empty); - if (!valid) - { - await WriteUtils.PrintErrorAsync(message); - return; - } - - await FileUtils.WriteTextAsync(_pathManager.GetWebRootPath("index.html"), Constants.Html5Empty); - - await WriteUtils.PrintSuccessAsync("Congratulations, SS CMS was installed successfully!"); - } - } -} diff --git a/src/SSCMS.Cli/Jobs/LoginJob.cs b/src/SSCMS.Cli/Jobs/LoginJob.cs index b99d2553c..3014b74aa 100644 --- a/src/SSCMS.Cli/Jobs/LoginJob.cs +++ b/src/SSCMS.Cli/Jobs/LoginJob.cs @@ -3,6 +3,7 @@ using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Plugins; namespace SSCMS.Cli.Jobs { @@ -31,7 +32,7 @@ public LoginJob(IApiService apiService) { "p|password=", "登录密码", v => _password = v }, { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -39,14 +40,14 @@ public LoginJob(IApiService apiService) public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: user login"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; diff --git a/src/SSCMS.Cli/Jobs/LogoutJob.cs b/src/SSCMS.Cli/Jobs/LogoutJob.cs index 8e4cf5666..58161c5e6 100644 --- a/src/SSCMS.Cli/Jobs/LogoutJob.cs +++ b/src/SSCMS.Cli/Jobs/LogoutJob.cs @@ -4,6 +4,7 @@ using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; using SSCMS.Cli.Models; +using SSCMS.Plugins; namespace SSCMS.Cli.Jobs { @@ -22,7 +23,7 @@ public LogoutJob(IConfigService configService) _options = new OptionSet { { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -30,14 +31,14 @@ public LogoutJob(IConfigService configService) public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: user logout"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; diff --git a/src/SSCMS.Cli/Jobs/PluginNewJob.cs b/src/SSCMS.Cli/Jobs/PluginNewJob.cs index 673ecce56..f6f02cc88 100644 --- a/src/SSCMS.Cli/Jobs/PluginNewJob.cs +++ b/src/SSCMS.Cli/Jobs/PluginNewJob.cs @@ -4,8 +4,9 @@ using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Configuration; using SSCMS.Core.Plugins; -using SSCMS.Core.Utils; +using SSCMS.Plugins; using SSCMS.Services; using SSCMS.Utils; @@ -30,7 +31,7 @@ public PluginNewJob(ISettingsManager settingsManager, IPathManager pathManager, _options = new OptionSet { { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -38,14 +39,14 @@ public PluginNewJob(ISettingsManager settingsManager, IPathManager pathManager, public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: creates a new plugin, includes configuration based on the specified parameters."); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; diff --git a/src/SSCMS.Cli/Jobs/PluginPackageJob.cs b/src/SSCMS.Cli/Jobs/PluginPackageJob.cs index bdb19d56a..c427264c2 100644 --- a/src/SSCMS.Cli/Jobs/PluginPackageJob.cs +++ b/src/SSCMS.Cli/Jobs/PluginPackageJob.cs @@ -3,8 +3,9 @@ using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Configuration; using SSCMS.Core.Plugins; -using SSCMS.Core.Utils; +using SSCMS.Plugins; using SSCMS.Services; using SSCMS.Utils; @@ -27,7 +28,7 @@ public PluginPackageJob(ISettingsManager settingsManager, IPathManager pathManag _options = new OptionSet { { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -35,14 +36,14 @@ public PluginPackageJob(ISettingsManager settingsManager, IPathManager pathManag public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: package plugin to zip file"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -69,13 +70,13 @@ public async Task ExecuteAsync(IJobContext context) return; } - var zipPath = Package(plugin); + var zipPath = Package(_pathManager, plugin); var fileSize = FileUtils.GetFileSizeByFilePath(zipPath); await WriteUtils.PrintSuccessAsync($"Packaged: {zipPath} ({fileSize})"); } - public static string Package(Plugin plugin) + public static string Package(IPathManager pathManager, Plugin plugin) { var outputPath = PathUtils.Combine(plugin.ContentRootPath, plugin.Output); var packageId = PluginUtils.GetPackageId(plugin.Publisher, plugin.Name, plugin.Version); @@ -131,7 +132,7 @@ public static string Package(Plugin plugin) } } - ZipUtils.CreateZip(zipPath, publishPath); + pathManager.CreateZip(zipPath, publishPath); DirectoryUtils.DeleteDirectoryIfExists(publishPath); return zipPath; diff --git a/src/SSCMS.Cli/Jobs/PluginPublishJob.cs b/src/SSCMS.Cli/Jobs/PluginPublishJob.cs index 917bd24b6..52b54ff2a 100644 --- a/src/SSCMS.Cli/Jobs/PluginPublishJob.cs +++ b/src/SSCMS.Cli/Jobs/PluginPublishJob.cs @@ -5,6 +5,7 @@ using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; using SSCMS.Core.Plugins; +using SSCMS.Plugins; using SSCMS.Services; using SSCMS.Utils; @@ -32,7 +33,7 @@ public PluginPublishJob(ISettingsManager settingsManager, IPathManager pathManag { "v|version=", "发布版本", v => _version = v }, { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -40,14 +41,14 @@ public PluginPublishJob(ISettingsManager settingsManager, IPathManager pathManag public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: publish plugin to marketplace"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -121,7 +122,7 @@ public async Task ExecuteAsync(IJobContext context) } var packageId = PluginUtils.GetPackageId(plugin.Publisher, plugin.Name, plugin.Version); - var zipPath = PluginPackageJob.Package(plugin); + var zipPath = PluginPackageJob.Package(_pathManager, plugin); var fileSize = FileUtils.GetFileSizeByFilePath(zipPath); await Console.Out.WriteLineAsync($"Packaged: {zipPath}"); diff --git a/src/SSCMS.Cli/Jobs/PluginSearchJob.cs b/src/SSCMS.Cli/Jobs/PluginSearchJob.cs index b65b2504f..df5995900 100644 --- a/src/SSCMS.Cli/Jobs/PluginSearchJob.cs +++ b/src/SSCMS.Cli/Jobs/PluginSearchJob.cs @@ -3,6 +3,7 @@ using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Plugins; using SSCMS.Utils; namespace SSCMS.Cli.Jobs @@ -22,7 +23,7 @@ public PluginSearchJob(IApiService apiService) _options = new OptionSet { { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -30,14 +31,14 @@ public PluginSearchJob(IApiService apiService) public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName} "); + Console.WriteLine($"Usage: sscms {CommandName} "); Console.WriteLine("Summary: search plugins by word"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; diff --git a/src/SSCMS.Cli/Jobs/PluginShowJob.cs b/src/SSCMS.Cli/Jobs/PluginShowJob.cs index baf0df821..b868bc771 100644 --- a/src/SSCMS.Cli/Jobs/PluginShowJob.cs +++ b/src/SSCMS.Cli/Jobs/PluginShowJob.cs @@ -3,6 +3,7 @@ using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Plugins; using SSCMS.Utils; namespace SSCMS.Cli.Jobs @@ -22,7 +23,7 @@ public PluginShowJob(IApiService apiService) _options = new OptionSet { { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -30,14 +31,14 @@ public PluginShowJob(IApiService apiService) public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName} "); + Console.WriteLine($"Usage: sscms {CommandName} "); Console.WriteLine("Summary: show plugin metadata"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; diff --git a/src/SSCMS.Cli/Jobs/PluginUnPublishJob.cs b/src/SSCMS.Cli/Jobs/PluginUnPublishJob.cs index 33c108c84..3042bbfbd 100644 --- a/src/SSCMS.Cli/Jobs/PluginUnPublishJob.cs +++ b/src/SSCMS.Cli/Jobs/PluginUnPublishJob.cs @@ -3,6 +3,7 @@ using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Plugins; namespace SSCMS.Cli.Jobs { @@ -21,7 +22,7 @@ public PluginUnPublishJob(IApiService apiService) _options = new OptionSet { { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -29,14 +30,14 @@ public PluginUnPublishJob(IApiService apiService) public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName} "); + Console.WriteLine($"Usage: sscms {CommandName} "); Console.WriteLine("Summary: unpublishes a plugin. Example plugin id: sscms.hits"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; diff --git a/src/SSCMS.Cli/Jobs/RegisterJob.cs b/src/SSCMS.Cli/Jobs/RegisterJob.cs index 7ea8e839b..df26cb7a3 100644 --- a/src/SSCMS.Cli/Jobs/RegisterJob.cs +++ b/src/SSCMS.Cli/Jobs/RegisterJob.cs @@ -3,6 +3,7 @@ using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Plugins; using SSCMS.Utils; namespace SSCMS.Cli.Jobs @@ -34,7 +35,7 @@ public RegisterJob(IApiService apiService) { "p|password=", "登录密码", v => _password = v }, { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -42,14 +43,14 @@ public RegisterJob(IApiService apiService) public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: register a new user"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -81,7 +82,7 @@ await WriteUtils.PrintErrorAsync( var (success, failureMessage) = _apiService.Register(_userName, _mobile, _email, _password); if (success) { - await WriteUtils.PrintSuccessAsync("you have registered successfully, run sscms-cli login to log in."); + await WriteUtils.PrintSuccessAsync("you have registered successfully, run sscms login to log in."); } else { diff --git a/src/SSCMS.Cli/Jobs/RunJob.cs b/src/SSCMS.Cli/Jobs/RunJob.cs index d2fb95363..04a85c681 100644 --- a/src/SSCMS.Cli/Jobs/RunJob.cs +++ b/src/SSCMS.Cli/Jobs/RunJob.cs @@ -1,12 +1,12 @@ using System; using System.Diagnostics; -using System.IO; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Plugins; namespace SSCMS.Cli.Jobs { @@ -23,7 +23,7 @@ public RunJob() _options = new OptionSet { { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -31,14 +31,14 @@ public RunJob() public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: run sscms"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -48,18 +48,27 @@ public async Task ExecuteAsync(IJobContext context) return; } - var psi = new ProcessStartInfo("./sscms") { RedirectStandardOutput = true }; - var proc = Process.Start(psi); + Process proc; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var psi = new ProcessStartInfo("./SSCMS.Web") { RedirectStandardOutput = true }; + proc = Process.Start(psi); + } + else + { + proc = Process.Start("./SSCMS.Web"); + } + if (proc == null) { - await WriteUtils.PrintErrorAsync("Can not run sscms."); + await WriteUtils.PrintErrorAsync("Can not run SSCMS."); } else { Console.WriteLine("Starting SS CMS..."); - Thread.Sleep(3000); + Thread.Sleep(5000); - OpenUrl("http://localhost:5000"); + OpenUrl("http://localhost:5000/ss-admin/"); using var sr = proc.StandardOutput; while (!sr.EndOfStream) @@ -78,29 +87,32 @@ private void OpenUrl(string url) { try { - Process.Start(url); - } - catch - { - // hack because of this: https://github.com/dotnet/corefx/issues/10361 - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - url = url.Replace("&", "^&"); - Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true }); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - Process.Start("xdg-open", url); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + try { - Process.Start("open", url); + Process.Start(url); } - else + catch { - throw; + // hack because of this: https://github.com/dotnet/corefx/issues/10361 + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + url = url.Replace("&", "^&"); + Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") {CreateNoWindow = true}); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Process.Start("xdg-open", url); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Process.Start("open", url); + } } } + catch + { + // ignored + } } } } \ No newline at end of file diff --git a/src/SSCMS.Cli/Jobs/StatusJob.cs b/src/SSCMS.Cli/Jobs/StatusJob.cs index 6f6e93ac4..f51164720 100644 --- a/src/SSCMS.Cli/Jobs/StatusJob.cs +++ b/src/SSCMS.Cli/Jobs/StatusJob.cs @@ -1,9 +1,13 @@ using System; +using System.Reflection; using System.Threading.Tasks; +using Datory; using Mono.Options; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Plugins; using SSCMS.Services; +using SSCMS.Utils; namespace SSCMS.Cli.Jobs { @@ -14,17 +18,19 @@ public class StatusJob : IJobService private bool _isHelp; private readonly ISettingsManager _settingsManager; + private readonly IPluginManager _pluginManager; private readonly IApiService _apiService; private readonly OptionSet _options; - public StatusJob(ISettingsManager settingsManager, IApiService apiService) + public StatusJob(ISettingsManager settingsManager, IPluginManager pluginManager, IApiService apiService) { _settingsManager = settingsManager; + _pluginManager = pluginManager; _apiService = apiService; _options = new OptionSet { { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -32,14 +38,14 @@ public StatusJob(ISettingsManager settingsManager, IApiService apiService) public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: show user login status"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -49,7 +55,41 @@ public async Task ExecuteAsync(IJobContext context) return; } - await WriteUtils.PrintInfoAsync(_settingsManager); + await Console.Out.WriteLineAsync($"Cli version: {_settingsManager.Version}"); + var entryAssembly = Assembly.GetExecutingAssembly(); + await Console.Out.WriteLineAsync($"Cli location: {entryAssembly.Location}"); + await Console.Out.WriteLineAsync($"Work location: {_settingsManager.ContentRootPath}"); + + var configPath = CliUtils.GetConfigPath(_settingsManager); + if (FileUtils.IsFileExists(configPath)) + { + await Console.Out.WriteLineAsync($"Database type: {_settingsManager.Database.DatabaseType.GetDisplayName()}"); + await Console.Out.WriteLineAsync($"Database connection string: {_settingsManager.DatabaseConnectionString}"); + + if (!string.IsNullOrEmpty(_settingsManager.DatabaseConnectionString)) + { + var (isConnectionWorks, errorMessage) = + await _settingsManager.Database.IsConnectionWorksAsync(); + + if (!isConnectionWorks) + { + await WriteUtils.PrintErrorAsync($"Unable to connect to database, error message:{errorMessage}"); + return; + } + + await Console.Out.WriteLineAsync("Database status: Connection successful"); + } + + var plugins = _pluginManager.Plugins; + foreach (var plugin in plugins) + { + await Console.Out.WriteLineAsync($"PluginId: {plugin.PluginId}, Version: {plugin.Version}"); + } + } + else + { + await Console.Out.WriteLineAsync($"The sscms.json file does not exist: {configPath}"); + } var (status, _) = _apiService.GetStatus(); if (status != null) diff --git a/src/SSCMS.Cli/Jobs/UpdateJob.cs b/src/SSCMS.Cli/Jobs/UpdateJob.cs index 0b67c2818..59f2cc6ea 100644 --- a/src/SSCMS.Cli/Jobs/UpdateJob.cs +++ b/src/SSCMS.Cli/Jobs/UpdateJob.cs @@ -1,11 +1,12 @@ using System; -using System.Linq; using System.Threading.Tasks; using Mono.Options; using Semver; using SSCMS.Cli.Abstractions; using SSCMS.Cli.Core; +using SSCMS.Configuration; using SSCMS.Core.Plugins; +using SSCMS.Plugins; using SSCMS.Repositories; using SSCMS.Services; using SSCMS.Utils; @@ -16,7 +17,6 @@ public class UpdateJob : IJobService { public string CommandName => "update"; - private bool? _isNightly; private bool _isHelp; private readonly IApiService _apiService; @@ -36,21 +36,7 @@ public UpdateJob(IApiService apiService, ISettingsManager settingsManager, IConf _options = new OptionSet { { - "nightly", "Update to nightly version", - v => - { - if (string.IsNullOrEmpty(v)) - { - _isNightly = null; - } - else - { - _isNightly = true; - } - } - }, - { - "h|help", "命令说明", + "h|help", "Display help", v => _isHelp = v != null } }; @@ -58,14 +44,14 @@ public UpdateJob(IApiService apiService, ISettingsManager settingsManager, IConf public void PrintUsage() { - Console.WriteLine($"Usage: sscms-cli {CommandName}"); + Console.WriteLine($"Usage: sscms {CommandName}"); Console.WriteLine("Summary: update sscms"); Console.WriteLine("Options:"); _options.WriteOptionDescriptions(Console.Out); Console.WriteLine(); } - public async Task ExecuteAsync(IJobContext context) + public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) return; @@ -82,9 +68,7 @@ public async Task ExecuteAsync(IJobContext context) return; } - var isNightly = _isNightly ?? _settingsManager.IsNightlyUpdate; - - var (success, result, failureMessage) = _apiService.GetReleases(isNightly, _settingsManager.Version, null); + var (success, result, failureMessage) = _apiService.GetReleases(_settingsManager.Version, null); if (!success) { await WriteUtils.PrintErrorAsync(failureMessage); @@ -93,37 +77,81 @@ public async Task ExecuteAsync(IJobContext context) if (!SemVersion.TryParse(result.Cms.Version, out var version) || version <= _settingsManager.Version) { - await WriteUtils.PrintErrorAsync("SS CMS is the latest version and no update is required"); - return; + Console.WriteLine($"SS CMS {result.Cms.Version} is the latest version and no update is required"); + var proceed = ReadUtils.GetYesNo("do you still want to update?"); + if (!proceed) return; + } + else + { + var proceed = ReadUtils.GetYesNo($"New version {result.Cms.Version} found, do you want to update?"); + if (!proceed) return; } - var proceed = ReadUtils.GetYesNo($"New version {result.Cms.Version} found, do you want to update?"); - if (!proceed) return; - - Console.WriteLine($"Downloading {result.Cms.Version}..."); - CloudUtils.Dl.DownloadCms(_pathManager, result.Cms.Version); - var name = CloudUtils.Dl.GetCmsDownloadName(result.Cms.Version); - var packagePath = _pathManager.GetPackagesPath(name); + Console.WriteLine($"Downloading SS CMS {result.Cms.Version}..."); + var directoryPath = CloudUtils.Dl.DownloadCms(_pathManager, _settingsManager.OSArchitecture, result.Cms.Version); - var offlinePath = PathUtils.Combine(_settingsManager.ContentRootPath, "app_offline.htm"); - FileUtils.WriteText(offlinePath, "down for maintenance"); + FileUtils.DeleteFileIfExists(PathUtils.Combine(directoryPath, Constants.ConfigFileName)); + FileUtils.DeleteFileIfExists(PathUtils.Combine(directoryPath, "wwwroot/404.html")); + FileUtils.DeleteFileIfExists(PathUtils.Combine(directoryPath, "wwwroot/favicon.ico")); + FileUtils.DeleteFileIfExists(PathUtils.Combine(directoryPath, "wwwroot/index.html")); - foreach (var fileName in DirectoryUtils.GetFileNames(packagePath).Where(fileName => - !StringUtils.EqualsIgnoreCase(fileName, $"{name}.zip") && - !StringUtils.EqualsIgnoreCase(fileName, Constants.ConfigFileName))) - { - FileUtils.CopyFile(PathUtils.Combine(packagePath, fileName), - PathUtils.Combine(contentRootPath, fileName), true); - } + await WriteUtils.PrintSuccessAsync($"{result.Cms.Version} download successfully!"); + Console.WriteLine(); + Console.WriteLine(); - foreach (var directoryName in DirectoryUtils.GetDirectoryNames(packagePath)) - { - DirectoryUtils.Copy(PathUtils.Combine(packagePath, directoryName), PathUtils.Combine(contentRootPath, directoryName), true); - } + Console.WriteLine("Please stop website and override files and directories "); + Console.WriteLine($" {directoryPath}"); + Console.WriteLine("to"); + Console.WriteLine($" {contentRootPath}"); - FileUtils.DeleteFileIfExists(offlinePath); + var offlinePath = _pathManager.GetPackagesPath("app_offline.htm"); + FileUtils.WriteText(offlinePath, "down for maintenance"); - await WriteUtils.PrintSuccessAsync($"Congratulations, SS CMS was updated to {result.Cms.Version} successfully!"); + //var unOverrides = new List(); + //foreach (var fileName in DirectoryUtils.GetFileNames(directoryPath)) + //{ + // if (!FileUtils.CopyFile(PathUtils.Combine(directoryPath, fileName), + // PathUtils.Combine(contentRootPath, fileName), true)) + // { + // unOverrides.Add(fileName); + // } + //} + + //foreach (var directoryName in DirectoryUtils.GetDirectoryNames(directoryPath)) + //{ + // DirectoryUtils.Copy(PathUtils.Combine(directoryPath, directoryName), PathUtils.Combine(contentRootPath, directoryName), true); + //} + + //if (unOverrides.Count > 0) + //{ + // Replacing(contentRootPath, directoryPath, unOverrides); + //} + + //FileUtils.DeleteFileIfExists(offlinePath); + + //await WriteUtils.PrintSuccessAsync($"Congratulations, SS CMS was updated to {result.Cms.Version} successfully!"); } + + //public static void Replacing(string contentRootPath, string directoryPath, List unOverrides) + //{ + // Thread.Sleep(1000); + // var list = new List(); + + // foreach (var unOverride in unOverrides) + // { + // Console.WriteLine($"Replacing {unOverride}..."); + + // if (!FileUtils.CopyFile(PathUtils.Combine(directoryPath, unOverride), + // PathUtils.Combine(contentRootPath, unOverride), true)) + // { + // list.Add(unOverride); + // } + // } + + // if (list.Count > 0) + // { + // Replacing(contentRootPath, directoryPath, list); + // } + //} } } diff --git a/src/SSCMS.Cli/Models/Config.cs b/src/SSCMS.Cli/Models/Config.cs index 86cfc56c0..d273ec218 100644 --- a/src/SSCMS.Cli/Models/Config.cs +++ b/src/SSCMS.Cli/Models/Config.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SSCMS.Cli.Models +namespace SSCMS.Cli.Models { public class Config { diff --git a/src/SSCMS.Cli/Models/ConfigStatus.cs b/src/SSCMS.Cli/Models/ConfigStatus.cs index 507bd2209..a3bcf17c9 100644 --- a/src/SSCMS.Cli/Models/ConfigStatus.cs +++ b/src/SSCMS.Cli/Models/ConfigStatus.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SSCMS.Cli.Models +namespace SSCMS.Cli.Models { public class ConfigStatus { diff --git a/src/SSCMS.Cli/Program.cs b/src/SSCMS.Cli/Program.cs index eab3355ca..d5666f085 100644 --- a/src/SSCMS.Cli/Program.cs +++ b/src/SSCMS.Cli/Program.cs @@ -13,11 +13,15 @@ using SSCMS.Core.Plugins.Extensions; using SSCMS.Utils; using Serilog; +using SSCMS.Cli.Abstractions; +using SSCMS.Configuration; namespace SSCMS.Cli { internal static class Program { + public static IApplication Application { get; private set; } + static async Task Main(string[] args) { try @@ -50,7 +54,7 @@ static async Task Main(string[] args) var configuration = builder.Build(); Log.Logger = new LoggerConfiguration() - .WriteTo.File("log/log.log", rollingInterval: RollingInterval.Day) + .WriteTo.File("logs/cli/log.log", rollingInterval: RollingInterval.Day) .Enrich.FromLogContext() .CreateLogger(); @@ -59,12 +63,11 @@ static async Task Main(string[] args) var entryAssembly = Assembly.GetExecutingAssembly(); var assemblies = new List { entryAssembly }.Concat(entryAssembly.GetReferencedAssemblies().Select(Assembly.Load)); - var settingsManager = services.AddSettingsManager(configuration, contentRootPath, PathUtils.Combine(contentRootPath, "wwwroot"), entryAssembly); - services.AddPlugins(configuration, settingsManager); + var settingsManager = services.AddSettingsManager(configuration, contentRootPath, PathUtils.Combine(contentRootPath, Constants.WwwrootDirectory), entryAssembly); + var pluginManager = services.AddPlugins(configuration, settingsManager); - var application = new Application(settingsManager); + Application = new Application(settingsManager, pluginManager); services.AddSingleton(configuration); - services.AddSingleton(application); services.AddCache(settingsManager.Redis.ConnectionString); services.AddRepositories(assemblies); @@ -72,11 +75,7 @@ static async Task Main(string[] args) services.AddCliServices(); services.AddCliJobs(); - var provider = services.BuildServiceProvider(); - - CliUtils.SetProvider(provider); - - await application.RunAsync(args); + await Application.RunAsync(args); //try //{ diff --git a/src/SSCMS.Cli/SSCMS.Cli.csproj b/src/SSCMS.Cli/SSCMS.Cli.csproj index aa4a4b370..579ff1910 100644 --- a/src/SSCMS.Cli/SSCMS.Cli.csproj +++ b/src/SSCMS.Cli/SSCMS.Cli.csproj @@ -4,8 +4,7 @@ Exe netcoreapp3.1 logo.ico - 7.0.0-preview7 - ss + 7.0.0 diff --git a/src/SSCMS.Cli/Services/ApiService.Dto.cs b/src/SSCMS.Cli/Services/ApiService.Dto.cs deleted file mode 100644 index 9914ddb76..000000000 --- a/src/SSCMS.Cli/Services/ApiService.Dto.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace SSCMS.Cli.Services -{ - public partial class ApiService - { - public class StatusResult - { - public string UserName { get; set; } - public string DisplayName { get; set; } - public string Mobile { get; set; } - public string Email { get; set; } - } - - public class LoginRequest - { - public string Account { get; set; } - public string Password { get; set; } - public bool IsPersistent { get; set; } - } - - public class LoginResult - { - public string UserName { get; set; } - public string AccessToken { get; set; } - } - - public class RegisterRequest - { - public string UserName { get; set; } - public string Mobile { get; set; } - public string Email { get; set; } - public string Password { get; set; } - } - - public class PublishRequest - { - public string Account { get; set; } - public string Password { get; set; } - public bool IsPersistent { get; set; } - } - - public class PublishResult - { - public string UserName { get; set; } - public string AccessToken { get; set; } - } - - public class UnPublishRequest - { - public string PluginId { get; set; } - } - - public class SearchRequest - { - public string Word { get; set; } - } - - public class ShowRequest - { - public string PluginId { get; set; } - } - - public class PluginAndUser - { - public Dictionary Plugin { get; set; } - public Dictionary User { get; set; } - } - - public class GetReleasesRequest - { - public bool IsNightly { get; set; } - public string Version { get; set; } - public List PluginIds { get; set; } - } - - public class GetReleasesCms - { - public string Version { get; set; } - public string Published { get; set; } - } - - public class GetReleasesPlugin - { - public string PluginId { get; set; } - public string Version { get; set; } - public string Published { get; set; } - } - - public class GetReleasesResult - { - public GetReleasesCms Cms { get; set; } - public List Plugins { get; set; } - } - } -} diff --git a/src/SSCMS.Cli/Services/ApiService.GetReleases.cs b/src/SSCMS.Cli/Services/ApiService.GetReleases.cs new file mode 100644 index 000000000..1707ca818 --- /dev/null +++ b/src/SSCMS.Cli/Services/ApiService.GetReleases.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace SSCMS.Cli.Services +{ + public partial class ApiService + { + public (bool success, GetReleasesResult result, string failureMessage) GetReleases(string version, List pluginIds) + { + //var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlReleases)) { Timeout = -1 }; + //var request = new RestRequest(Method.POST); + //request.AddHeader("Content-Type", "application/json"); + //request.AddParameter("application/json", TranslateUtils.JsonSerialize(new GetReleasesRequest + //{ + // IsNightly = isNightly, + // Version = version, + // PluginIds = pluginIds + //}), ParameterType.RequestBody); + //var response = client.Execute(request); + //if (!response.IsSuccessful) + //{ + // if (response.StatusCode == HttpStatusCode.InternalServerError) + // { + // Log.Fatal(response.Content); + // var error = TranslateUtils.JsonDeserialize(response.Content); + // if (error != null) + // { + // return (false, null, error.Message); + // } + // } + // return (false, null, response.ErrorMessage); + //} + + //return (true, response.Data, null); + + return ExecutePost(RestUrlReleases, new GetReleasesRequest + { + Version = version, + PluginIds = pluginIds + }); + } + } +} diff --git a/src/SSCMS.Cli/Services/ApiService.GetStatus.cs b/src/SSCMS.Cli/Services/ApiService.GetStatus.cs new file mode 100644 index 000000000..ca15c0e6f --- /dev/null +++ b/src/SSCMS.Cli/Services/ApiService.GetStatus.cs @@ -0,0 +1,31 @@ +using RestSharp; +using SSCMS.Cli.Models; +using SSCMS.Core.Plugins; + +namespace SSCMS.Cli.Services +{ + public partial class ApiService + { + public (ConfigStatus status, string failureMessage) GetStatus() + { + var status = _configService.Status; + if (status == null || string.IsNullOrEmpty(status.UserName) || string.IsNullOrEmpty(status.AccessToken)) + { + return (null, "you have not logged in"); + } + + var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlStatus)) { Timeout = -1 }; + var request = new RestRequest(Method.GET); + request.AddHeader("Content-Type", "application/json"); + request.AddHeader("Authorization", $"Bearer {status.AccessToken}"); + var response = client.Execute(request); + + if (!response.IsSuccessful || response.Data.UserName != status.UserName) + { + return (null, "you have not logged in"); + } + + return (status, null); + } + } +} diff --git a/src/SSCMS.Cli/Services/ApiService.LoginAsync.cs b/src/SSCMS.Cli/Services/ApiService.LoginAsync.cs new file mode 100644 index 000000000..ed8437e8b --- /dev/null +++ b/src/SSCMS.Cli/Services/ApiService.LoginAsync.cs @@ -0,0 +1,41 @@ +using System.Threading.Tasks; +using RestSharp; +using SSCMS.Cli.Models; +using SSCMS.Core.Plugins; +using SSCMS.Utils; + +namespace SSCMS.Cli.Services +{ + public partial class ApiService + { + public async Task<(bool success, string failureMessage)> LoginAsync(string account, string password) + { + var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlLogin)) { Timeout = -1 }; + var request = new RestRequest(Method.POST); + request.AddHeader("Content-Type", "application/json"); + request.AddParameter("application/json", TranslateUtils.JsonSerialize(new LoginRequest + { + Account = account, + Password = AuthUtils.Md5ByString(password), + IsPersistent = true + }), ParameterType.RequestBody); + var response = client.Execute(request); + if (!response.IsSuccessful) + { + return (false, "your account or password was incorrect"); + } + + var loginResult = response.Data; + + var status = new ConfigStatus + { + UserName = loginResult.UserName, + AccessToken = loginResult.AccessToken + }; + + await _configService.SaveStatusAsync(status); + + return (true, null); + } + } +} diff --git a/src/SSCMS.Cli/Services/ApiService.PluginsPublish.cs b/src/SSCMS.Cli/Services/ApiService.PluginsPublish.cs new file mode 100644 index 000000000..ebfa36069 --- /dev/null +++ b/src/SSCMS.Cli/Services/ApiService.PluginsPublish.cs @@ -0,0 +1,32 @@ +using RestSharp; +using SSCMS.Core.Plugins; +using SSCMS.Utils; + +namespace SSCMS.Cli.Services +{ + public partial class ApiService + { + public (bool success, string failureMessage) PluginsPublish(string publisher, string zipPath) + { + var status = _configService.Status; + if (status == null || string.IsNullOrEmpty(status.UserName) || string.IsNullOrEmpty(status.AccessToken)) + { + return (false, "you have not logged in"); + } + + if (status.UserName != publisher) + { + return (false, $"the publisher in package.json should be '{status.UserName}'"); + } + + var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlPluginPublish)) { Timeout = -1 }; + var request = new RestRequest(Method.POST); + //request.AddHeader("Content-Type", "multipart/form-data"); + request.AddHeader("Authorization", $"Bearer {status.AccessToken}"); + request.AddFile("file", zipPath); + var response = client.Execute(request); + + return response.IsSuccessful ? (true, null) : (false, StringUtils.Trim(response.Content, '"')); + } + } +} diff --git a/src/SSCMS.Cli/Services/ApiService.PluginsSearch.cs b/src/SSCMS.Cli/Services/ApiService.PluginsSearch.cs new file mode 100644 index 000000000..18b4be3ce --- /dev/null +++ b/src/SSCMS.Cli/Services/ApiService.PluginsSearch.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; + +namespace SSCMS.Cli.Services +{ + public partial class ApiService + { + public (bool success, List results, string failureMessage) PluginsSearch(string word) + { + //var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlPluginSearch)) { Timeout = -1 }; + //var request = new RestRequest(Method.POST); + //request.AddHeader("Content-Type", "application/json"); + //request.AddParameter("application/json", TranslateUtils.JsonSerialize(new SearchRequest + //{ + // Word = word + //}), ParameterType.RequestBody); + //var response = client.Execute>(request); + //if (!response.IsSuccessful) + //{ + // return (false, null, response.ErrorMessage); + //} + + //return (true, response.Data, null); + + return ExecutePost>(RestUrlPluginSearch, new SearchRequest + { + Word = word + }); + } + } +} diff --git a/src/SSCMS.Cli/Services/ApiService.PluginsShow.cs b/src/SSCMS.Cli/Services/ApiService.PluginsShow.cs new file mode 100644 index 000000000..91793ff1a --- /dev/null +++ b/src/SSCMS.Cli/Services/ApiService.PluginsShow.cs @@ -0,0 +1,28 @@ +namespace SSCMS.Cli.Services +{ + public partial class ApiService + { + public (bool success, PluginAndUser result, string failureMessage) PluginsShow(string pluginId) + { + //var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlPluginShow)) { Timeout = -1 }; + //var request = new RestRequest(Method.POST); + //request.AddHeader("Content-Type", "application/json"); + //request.AddParameter("application/json", TranslateUtils.JsonSerialize(new ShowRequest + //{ + // PluginId = pluginId + //}), ParameterType.RequestBody); + //var response = client.Execute(request); + //if (!response.IsSuccessful) + //{ + // return (false, null, response.ErrorMessage); + //} + + //return (true, response.Data, null); + + return ExecutePost(RestUrlPluginShow, new ShowRequest + { + PluginId = pluginId + }); + } + } +} diff --git a/src/SSCMS.Cli/Services/ApiService.Register.cs b/src/SSCMS.Cli/Services/ApiService.Register.cs new file mode 100644 index 000000000..be3dd37ea --- /dev/null +++ b/src/SSCMS.Cli/Services/ApiService.Register.cs @@ -0,0 +1,26 @@ +using RestSharp; +using SSCMS.Core.Plugins; +using SSCMS.Utils; + +namespace SSCMS.Cli.Services +{ + public partial class ApiService + { + public (bool success, string failureMessage) Register(string userName, string mobile, string email, string password) + { + var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlRegister)) { Timeout = -1 }; + var request = new RestRequest(Method.POST); + request.AddHeader("Content-Type", "application/json"); + request.AddParameter("application/json", TranslateUtils.JsonSerialize(new RegisterRequest + { + UserName = userName, + Mobile = mobile, + Email = email, + Password = password + }), ParameterType.RequestBody); + var response = client.Execute(request); + + return response.IsSuccessful ? (true, null) : (false, StringUtils.Trim(response.Content, '"')); + } + } +} diff --git a/src/SSCMS.Cli/Services/ApiService.UnPluginsPublish.cs b/src/SSCMS.Cli/Services/ApiService.UnPluginsPublish.cs new file mode 100644 index 000000000..e2bf38c5c --- /dev/null +++ b/src/SSCMS.Cli/Services/ApiService.UnPluginsPublish.cs @@ -0,0 +1,34 @@ +using RestSharp; +using SSCMS.Core.Plugins; +using SSCMS.Utils; + +namespace SSCMS.Cli.Services +{ + public partial class ApiService + { + public (bool success, string failureMessage) UnPluginsPublish(string pluginId) + { + var status = _configService.Status; + if (status == null || string.IsNullOrEmpty(status.UserName) || string.IsNullOrEmpty(status.AccessToken)) + { + return (false, "you have not logged in"); + } + + var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlPluginUnPublish)) { Timeout = -1 }; + var request = new RestRequest(Method.POST); + request.AddHeader("Content-Type", "application/json"); + request.AddHeader("Authorization", $"Bearer {status.AccessToken}"); + request.AddParameter("application/json", TranslateUtils.JsonSerialize(new UnPublishRequest + { + PluginId = pluginId + }), ParameterType.RequestBody); + var response = client.Execute(request); + if (!response.IsSuccessful) + { + return (false, StringUtils.Trim(response.Content, '"')); + } + + return (true, null); + } + } +} diff --git a/src/SSCMS.Cli/Services/ApiService.cs b/src/SSCMS.Cli/Services/ApiService.cs index 793a57605..faf1ce444 100644 --- a/src/SSCMS.Cli/Services/ApiService.cs +++ b/src/SSCMS.Cli/Services/ApiService.cs @@ -1,10 +1,8 @@ using System.Collections.Generic; using System.Net; -using System.Threading.Tasks; using RestSharp; using Serilog; using SSCMS.Cli.Abstractions; -using SSCMS.Cli.Models; using SSCMS.Core.Plugins; using SSCMS.Utils; @@ -28,204 +26,94 @@ public ApiService(IConfigService configService) _configService = configService; } - public (ConfigStatus status, string failureMessage) GetStatus() + public class StatusResult { - var status = _configService.Status; - if (status == null || string.IsNullOrEmpty(status.UserName) || string.IsNullOrEmpty(status.AccessToken)) - { - return (null, "you have not logged in"); - } - - var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlStatus)) { Timeout = -1 }; - var request = new RestRequest(Method.GET); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Authorization", $"Bearer {status.AccessToken}"); - var response = client.Execute(request); - - if (!response.IsSuccessful || response.Data.UserName != status.UserName) - { - return (null, "you have not logged in"); - } - - return (status, null); + public string UserName { get; set; } + public string DisplayName { get; set; } + public string Mobile { get; set; } + public string Email { get; set; } } - public (bool success, string failureMessage) Register(string userName, string mobile, string email, string password) + public class LoginRequest { - var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlRegister)) {Timeout = -1}; - var request = new RestRequest(Method.POST); - request.AddHeader("Content-Type", "application/json"); - request.AddParameter("application/json", TranslateUtils.JsonSerialize(new RegisterRequest - { - UserName = userName, - Mobile = mobile, - Email = email, - Password = password - }), ParameterType.RequestBody); - var response = client.Execute(request); - - return response.IsSuccessful ? (true, null) : (false, StringUtils.Trim(response.Content, '"')); + public string Account { get; set; } + public string Password { get; set; } + public bool IsPersistent { get; set; } } - public async Task<(bool success, string failureMessage)> LoginAsync(string account, string password) + public class LoginResult { - var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlLogin)) { Timeout = -1 }; - var request = new RestRequest(Method.POST); - request.AddHeader("Content-Type", "application/json"); - request.AddParameter("application/json", TranslateUtils.JsonSerialize(new LoginRequest - { - Account = account, - Password = AuthUtils.Md5ByString(password), - IsPersistent = true - }), ParameterType.RequestBody); - var response = client.Execute(request); - if (!response.IsSuccessful) - { - return (false, $"your account or password was incorrect, status code: {response.StatusDescription}"); - } - - var loginResult = response.Data; - - var status = new ConfigStatus - { - UserName = loginResult.UserName, - AccessToken = loginResult.AccessToken - }; - - await _configService.SaveStatusAsync(status); - - return (true, null); + public string UserName { get; set; } + public string AccessToken { get; set; } } - public (bool success, string failureMessage) PluginsPublish(string publisher, string zipPath) + public class RegisterRequest { - var status = _configService.Status; - if (status == null || string.IsNullOrEmpty(status.UserName) || string.IsNullOrEmpty(status.AccessToken)) - { - return (false, "you have not logged in"); - } - - if (status.UserName != publisher) - { - return (false, $"the publisher in package.json should be '{status.UserName}'"); - } - - var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlPluginPublish)) {Timeout = -1}; - var request = new RestRequest(Method.POST); - //request.AddHeader("Content-Type", "multipart/form-data"); - request.AddHeader("Authorization", $"Bearer {status.AccessToken}"); - request.AddFile("file", zipPath); - var response = client.Execute(request); - - return response.IsSuccessful ? (true, null) : (false, StringUtils.Trim(response.Content, '"')); + public string UserName { get; set; } + public string Mobile { get; set; } + public string Email { get; set; } + public string Password { get; set; } } - public (bool success, string failureMessage) UnPluginsPublish(string pluginId) + public class PublishRequest { - var status = _configService.Status; - if (status == null || string.IsNullOrEmpty(status.UserName) || string.IsNullOrEmpty(status.AccessToken)) - { - return (false, "you have not logged in"); - } - - var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlPluginUnPublish)) { Timeout = -1 }; - var request = new RestRequest(Method.POST); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Authorization", $"Bearer {status.AccessToken}"); - request.AddParameter("application/json", TranslateUtils.JsonSerialize(new UnPublishRequest - { - PluginId = pluginId - }), ParameterType.RequestBody); - var response = client.Execute(request); - if (!response.IsSuccessful) - { - return (false, StringUtils.Trim(response.Content, '"')); - } - - return (true, null); + public string Account { get; set; } + public string Password { get; set; } + public bool IsPersistent { get; set; } } - public (bool success, List results, string failureMessage) PluginsSearch(string word) + public class PublishResult { - //var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlPluginSearch)) { Timeout = -1 }; - //var request = new RestRequest(Method.POST); - //request.AddHeader("Content-Type", "application/json"); - //request.AddParameter("application/json", TranslateUtils.JsonSerialize(new SearchRequest - //{ - // Word = word - //}), ParameterType.RequestBody); - //var response = client.Execute>(request); - //if (!response.IsSuccessful) - //{ - // return (false, null, response.ErrorMessage); - //} + public string UserName { get; set; } + public string AccessToken { get; set; } + } - //return (true, response.Data, null); + public class UnPublishRequest + { + public string PluginId { get; set; } + } - return ExecutePost>(RestUrlPluginSearch, new SearchRequest - { - Word = word - }); + public class SearchRequest + { + public string Word { get; set; } } - public (bool success, PluginAndUser result, string failureMessage) PluginsShow(string pluginId) + public class ShowRequest { - //var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlPluginShow)) { Timeout = -1 }; - //var request = new RestRequest(Method.POST); - //request.AddHeader("Content-Type", "application/json"); - //request.AddParameter("application/json", TranslateUtils.JsonSerialize(new ShowRequest - //{ - // PluginId = pluginId - //}), ParameterType.RequestBody); - //var response = client.Execute(request); - //if (!response.IsSuccessful) - //{ - // return (false, null, response.ErrorMessage); - //} + public string PluginId { get; set; } + } - //return (true, response.Data, null); + public class PluginAndUser + { + public Dictionary Plugin { get; set; } + public Dictionary User { get; set; } + } - return ExecutePost(RestUrlPluginShow, new ShowRequest - { - PluginId = pluginId - }); + public class GetReleasesRequest + { + public string Version { get; set; } + public List PluginIds { get; set; } } - public (bool success, GetReleasesResult result, string failureMessage) GetReleases(bool isNightly, string version, List pluginIds) + public class GetReleasesCms { - //var client = new RestClient(CloudUtils.Api.GetCliUrl(RestUrlReleases)) { Timeout = -1 }; - //var request = new RestRequest(Method.POST); - //request.AddHeader("Content-Type", "application/json"); - //request.AddParameter("application/json", TranslateUtils.JsonSerialize(new GetReleasesRequest - //{ - // IsNightly = isNightly, - // Version = version, - // PluginIds = pluginIds - //}), ParameterType.RequestBody); - //var response = client.Execute(request); - //if (!response.IsSuccessful) - //{ - // if (response.StatusCode == HttpStatusCode.InternalServerError) - // { - // Log.Fatal(response.Content); - // var error = TranslateUtils.JsonDeserialize(response.Content); - // if (error != null) - // { - // return (false, null, error.Message); - // } - // } - // return (false, null, response.ErrorMessage); - //} + public string Version { get; set; } + public string Published { get; set; } + } - //return (true, response.Data, null); + public class GetReleasesPlugin + { + public string PluginId { get; set; } + public string Version { get; set; } + public string Published { get; set; } + } - return ExecutePost(RestUrlReleases, new GetReleasesRequest - { - IsNightly = isNightly, - Version = version, - PluginIds = pluginIds - }); + public class GetReleasesResult + { + public GetReleasesCms Cms { get; set; } + public List Plugins { get; set; } } + private static (bool success, TResult result, string failureMessage) ExecutePost(string relatedUrl, TRequest body, string accessToken = null) where TResult : class diff --git a/src/SSCMS.Cli/Services/DataRestoreService.cs b/src/SSCMS.Cli/Services/DataRestoreService.cs index 8c5b4da9b..dce6191c8 100644 --- a/src/SSCMS.Cli/Services/DataRestoreService.cs +++ b/src/SSCMS.Cli/Services/DataRestoreService.cs @@ -17,14 +17,12 @@ public class DataRestoreService : IDataRestoreService private readonly ISettingsManager _settingsManager; private readonly IConfigRepository _configRepository; private readonly IDatabaseManager _databaseManager; - private readonly IOldPluginManager _pluginManager; - public DataRestoreService(ISettingsManager settingsManager, IConfigRepository configRepository, IDatabaseManager databaseManager, IOldPluginManager pluginManager) + public DataRestoreService(ISettingsManager settingsManager, IConfigRepository configRepository, IDatabaseManager databaseManager) { _settingsManager = settingsManager; _configRepository = configRepository; _databaseManager = databaseManager; - _pluginManager = pluginManager; } public async Task RestoreAsync(List includes, List excludes, bool dataOnly, string tablesFilePath, TreeInfo treeInfo, string errorLogFilePath) @@ -106,12 +104,13 @@ public async Task RestoreAsync(List includes, List excludes, boo await WriteUtils.PrintRowLineAsync(); - if (!dataOnly) - { - // 恢复后同步表,确保内容辅助表字段与系统一致 - await _databaseManager.SyncContentTablesAsync(_pluginManager); - await _configRepository.UpdateConfigVersionAsync(_settingsManager.Version); - } + //if (!dataOnly) + //{ + // // 恢复后同步表,确保内容辅助表字段与系统一致 + // await _databaseManager.SyncDatabaseAsync(); + // //await _databaseManager.SyncContentTablesAsync(); + // await _configRepository.UpdateConfigVersionAsync(_settingsManager.Version); + //} } } } diff --git a/src/SSCMS.Cli/Services/InternalServerError.cs b/src/SSCMS.Cli/Services/InternalServerError.cs index f2ea6ffec..3a519d631 100644 --- a/src/SSCMS.Cli/Services/InternalServerError.cs +++ b/src/SSCMS.Cli/Services/InternalServerError.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace SSCMS.Cli.Services { diff --git a/src/SSCMS.Cli/Updater/TableContentConverter.cs b/src/SSCMS.Cli/Updater/TableContentConverter.cs index a8ce20a99..93cf23897 100644 --- a/src/SSCMS.Cli/Updater/TableContentConverter.cs +++ b/src/SSCMS.Cli/Updater/TableContentConverter.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater diff --git a/src/SSCMS.Cli/Updater/Tables/GovInteract/TableGovInteractContent.cs b/src/SSCMS.Cli/Updater/Tables/GovInteract/TableGovInteractContent.cs index 30e99f3d6..a526b6374 100644 --- a/src/SSCMS.Cli/Updater/Tables/GovInteract/TableGovInteractContent.cs +++ b/src/SSCMS.Cli/Updater/Tables/GovInteract/TableGovInteractContent.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables.GovInteract diff --git a/src/SSCMS.Cli/Updater/Tables/GovPublic/TableGovPublicContent.cs b/src/SSCMS.Cli/Updater/Tables/GovPublic/TableGovPublicContent.cs index 85afb43d9..270eed7d4 100644 --- a/src/SSCMS.Cli/Updater/Tables/GovPublic/TableGovPublicContent.cs +++ b/src/SSCMS.Cli/Updater/Tables/GovPublic/TableGovPublicContent.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables.GovPublic diff --git a/src/SSCMS.Cli/Updater/Tables/Jobs/TableJobsContent.cs b/src/SSCMS.Cli/Updater/Tables/Jobs/TableJobsContent.cs index 5349e511d..27a63192f 100644 --- a/src/SSCMS.Cli/Updater/Tables/Jobs/TableJobsContent.cs +++ b/src/SSCMS.Cli/Updater/Tables/Jobs/TableJobsContent.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables.Jobs diff --git a/src/SSCMS.Cli/Updater/Tables/TableAdministrator.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableAdministrator.Utils.cs index 9ba0be029..1d0fd0679 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableAdministrator.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableAdministrator.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableAdministrator.cs b/src/SSCMS.Cli/Updater/Tables/TableAdministrator.cs index d6f2aebff..c6cc5f6f8 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableAdministrator.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableAdministrator.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableAdministratorsInRoles.cs b/src/SSCMS.Cli/Updater/Tables/TableAdministratorsInRoles.cs index 0ebb1542c..a9f9bf0a1 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableAdministratorsInRoles.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableAdministratorsInRoles.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableChannel.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableChannel.Utils.cs index e33a2d595..09bd0997c 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableChannel.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableChannel.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableChannel.cs b/src/SSCMS.Cli/Updater/Tables/TableChannel.cs index 555bf87da..e6f1cdc41 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableChannel.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableChannel.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableChannelGroup.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableChannelGroup.Utils.cs index 114109650..b7bde7a1d 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableChannelGroup.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableChannelGroup.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableChannelGroup.cs b/src/SSCMS.Cli/Updater/Tables/TableChannelGroup.cs index d3e53a729..6f8186c52 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableChannelGroup.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableChannelGroup.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableConfig.cs b/src/SSCMS.Cli/Updater/Tables/TableConfig.cs index 876af1790..d8a1b9383 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableConfig.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableConfig.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableContentCheck.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableContentCheck.Utils.cs index 8419c765f..f91b64e10 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableContentCheck.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableContentCheck.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableContentCheck.cs b/src/SSCMS.Cli/Updater/Tables/TableContentCheck.cs index 776593510..98761e0a0 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableContentCheck.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableContentCheck.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableContentGroup.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableContentGroup.Utils.cs index 8251dda3a..6be95d28e 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableContentGroup.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableContentGroup.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableContentGroup.cs b/src/SSCMS.Cli/Updater/Tables/TableContentGroup.cs index 51fe8b482..8e2f13c9a 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableContentGroup.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableContentGroup.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableContentTag.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableContentTag.Utils.cs index 6cf8910ab..25c87014e 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableContentTag.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableContentTag.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableContentTag.cs b/src/SSCMS.Cli/Updater/Tables/TableContentTag.cs index db5c60037..929cbe426 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableContentTag.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableContentTag.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableDbCache.cs b/src/SSCMS.Cli/Updater/Tables/TableDbCache.cs index 18ad72c60..9ee2bc47e 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableDbCache.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableDbCache.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableLog.cs b/src/SSCMS.Cli/Updater/Tables/TableLog.cs index 3c26cb495..a042985bd 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableLog.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableLog.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TablePermissionsInRoles.cs b/src/SSCMS.Cli/Updater/Tables/TablePermissionsInRoles.cs index 2dc2cf924..529e41947 100644 --- a/src/SSCMS.Cli/Updater/Tables/TablePermissionsInRoles.cs +++ b/src/SSCMS.Cli/Updater/Tables/TablePermissionsInRoles.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableRelatedField.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableRelatedField.Utils.cs index 6506cb91d..552087a53 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableRelatedField.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableRelatedField.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableRelatedField.cs b/src/SSCMS.Cli/Updater/Tables/TableRelatedField.cs index 8f07a8a45..fb1616479 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableRelatedField.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableRelatedField.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableRelatedFieldItem.cs b/src/SSCMS.Cli/Updater/Tables/TableRelatedFieldItem.cs index 700ed55b5..fa27c7730 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableRelatedFieldItem.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableRelatedFieldItem.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableRole.cs b/src/SSCMS.Cli/Updater/Tables/TableRole.cs index dc280ce6e..661849eb9 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableRole.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableRole.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableSite.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableSite.Utils.cs index 99dd2d9d9..c00836b82 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableSite.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableSite.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableSite.cs b/src/SSCMS.Cli/Updater/Tables/TableSite.cs index d5d2c458b..d2bec43e9 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableSite.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableSite.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableSiteLog.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableSiteLog.Utils.cs index 7f3b1cadf..07833c9b1 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableSiteLog.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableSiteLog.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableSiteLog.cs b/src/SSCMS.Cli/Updater/Tables/TableSiteLog.cs index c5eeef23f..83d87e928 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableSiteLog.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableSiteLog.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableSitePermissions.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableSitePermissions.Utils.cs index eb88aad88..25013a853 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableSitePermissions.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableSitePermissions.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableSitePermissions.cs b/src/SSCMS.Cli/Updater/Tables/TableSitePermissions.cs index 0b2991e74..6ccb0ac29 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableSitePermissions.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableSitePermissions.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableTableStyle.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableTableStyle.Utils.cs index 68cf3fa76..195b3b835 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableTableStyle.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableTableStyle.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; using SSCMS.Utils; diff --git a/src/SSCMS.Cli/Updater/Tables/TableTableStyle.cs b/src/SSCMS.Cli/Updater/Tables/TableTableStyle.cs index 2044a6bdb..31525d72c 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableTableStyle.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableTableStyle.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableTemplate.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableTemplate.Utils.cs index 288645043..1968274ec 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableTemplate.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableTemplate.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableTemplate.cs b/src/SSCMS.Cli/Updater/Tables/TableTemplate.cs index 04703bdf0..5df495800 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableTemplate.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableTemplate.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableTemplateLog.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableTemplateLog.Utils.cs index a11a2fb5a..98e9c4f6c 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableTemplateLog.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableTemplateLog.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableTemplateLog.cs b/src/SSCMS.Cli/Updater/Tables/TableTemplateLog.cs index 31b266cb6..98d69e7a0 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableTemplateLog.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableTemplateLog.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableUser.Utils.cs b/src/SSCMS.Cli/Updater/Tables/TableUser.Utils.cs index 4c9815645..6fa438873 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableUser.Utils.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableUser.Utils.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Datory; -using SSCMS; using SSCMS.Models; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Cli/Updater/Tables/TableUser.cs b/src/SSCMS.Cli/Updater/Tables/TableUser.cs index 1da1d0267..5ce83f0d9 100644 --- a/src/SSCMS.Cli/Updater/Tables/TableUser.cs +++ b/src/SSCMS.Cli/Updater/Tables/TableUser.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using SSCMS; using SSCMS.Services; namespace SSCMS.Cli.Updater.Tables diff --git a/src/SSCMS.Core/Context/PluginParseContext.cs b/src/SSCMS.Core/Context/PluginParseContext.cs new file mode 100644 index 000000000..12dc8833d --- /dev/null +++ b/src/SSCMS.Core/Context/PluginParseContext.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using SSCMS.Enums; +using SSCMS.Parse; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Core.Context +{ + public class PluginParseContext : IParseContext + { + protected readonly IParseManager ParseManager; + + public PluginParseContext(IParseManager parseManager) + { + ParseManager = parseManager; + } + + public void Set(string key, T objectValue) + { + if (!string.IsNullOrEmpty(key)) + { + ParseManager.PageInfo.PluginItems[key] = objectValue; + } + } + + public T Get(string key) + { + return TranslateUtils.Get(ParseManager.PageInfo.PluginItems, key); + } + + public int SiteId => ParseManager.ContextInfo.Site.Id; + + public int ChannelId => ParseManager.ContextInfo.ChannelId; + + public int ContentId => ParseManager.ContextInfo.ContentId; + + public TemplateType TemplateType => ParseManager.PageInfo.Template.TemplateType; + + public int TemplateId => ParseManager.PageInfo.Template.Id; + + public SortedDictionary HeadCodes => ParseManager.PageInfo.HeadCodes; + + public SortedDictionary BodyCodes => ParseManager.PageInfo.BodyCodes; + + public SortedDictionary FootCodes => ParseManager.PageInfo.FootCodes; + + public async Task ParseAsync(string template) + { + var builder = new StringBuilder(template); + await ParseManager.ParseInnerContentAsync(builder); + return builder.ToString(); + } + } +} diff --git a/src/SSCMS.Core/Context/PluginParseStlContext.cs b/src/SSCMS.Core/Context/PluginParseStlContext.cs new file mode 100644 index 000000000..6fe7fae03 --- /dev/null +++ b/src/SSCMS.Core/Context/PluginParseStlContext.cs @@ -0,0 +1,24 @@ +using System.Collections.Specialized; +using SSCMS.Parse; +using SSCMS.Services; + +namespace SSCMS.Core.Context +{ + public class PluginParseStlContext : PluginParseContext, IParseStlContext + { + public PluginParseStlContext(IParseManager parseManager, string stlOuterHtml, string stlInnerHtml, NameValueCollection stlAttributes) : base(parseManager) + { + StlOuterHtml = stlOuterHtml; + StlInnerHtml = stlInnerHtml; + StlAttributes = stlAttributes; + } + + public string StlOuterHtml { get; } + + public string StlInnerHtml { get; } + + public NameValueCollection StlAttributes { get; } + + public bool IsStlEntity => ParseManager.ContextInfo.IsStlEntity; + } +} diff --git a/src/SSCMS.Core/Extensions/ServiceCollectionExtensions.cs b/src/SSCMS.Core/Extensions/ServiceCollectionExtensions.cs index c2ee5ee99..70c5f8877 100644 --- a/src/SSCMS.Core/Extensions/ServiceCollectionExtensions.cs +++ b/src/SSCMS.Core/Extensions/ServiceCollectionExtensions.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Senparc.CO2NET.RegisterServices; using SSCMS.Core.Services; using SSCMS.Services; @@ -102,12 +103,18 @@ public static void AddTaskQueue(this IServiceCollection services) public static void AddServices(this IServiceCollection services) { + services.AddScoped(typeof(SSCMS.Services.ICacheManager<>), typeof(CacheManager<>)); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); + } + + public static void AddWxManager(this IServiceCollection services, IConfiguration configuration) + { + services.AddSenparcGlobalServices(configuration); + services.AddScoped(); } } } \ No newline at end of file diff --git a/src/SSCMS.Core/Plugins/CloudUtils.cs b/src/SSCMS.Core/Plugins/CloudUtils.cs index 65296f4a7..66026b61e 100644 --- a/src/SSCMS.Core/Plugins/CloudUtils.cs +++ b/src/SSCMS.Core/Plugins/CloudUtils.cs @@ -1,7 +1,6 @@ using System.IO; using System.Linq; using RestSharp; -using SSCMS.Core.Utils; using SSCMS.Services; using SSCMS.Utils; @@ -21,8 +20,8 @@ public static string GetPluginUrl(string pluginId) public static class Api { - //private const string Host = "https://api.sscms.com"; - private const string Host = "https://localhost:6001"; + private const string Host = "https://api.sscms.com"; + // private const string Host = "http://localhost:81"; public static string GetCliUrl(string relatedUrl) { @@ -34,14 +33,14 @@ public static class Dl { private const string Host = "https://dl.sscms.com"; - public static string GetCmsDownloadName(string version) + public static string GetCmsDownloadName(string osArchitecture, string version) { - return $"sscms-{version}-{Constants.OperatingSystem}"; + return $"sscms-{version}-{osArchitecture}"; } - public static string GetCmsDownloadUrl(string version) + public static string GetCmsDownloadUrl(string osArchitecture, string version) { - return $"{Host}/cms/{version}/{GetCmsDownloadName(version)}.zip"; + return $"{Host}/cms/{version}/{GetCmsDownloadName(osArchitecture, version)}.zip"; } public static string GetPluginsDownloadUrl(string pluginId, string version) @@ -55,15 +54,16 @@ public static string GetPluginsDownloadName(string pluginId, string version) return $"{pluginId}.{version}"; } - public static void DownloadCms(IPathManager pathManager, string version) + public static string DownloadCms(IPathManager pathManager, string osArchitecture, string version) { - if (IsCmsDownload(pathManager, version)) - { - return; - } - var packagesPath = pathManager.GetPackagesPath(); - var name = GetCmsDownloadName(version); + var name = GetCmsDownloadName(osArchitecture, version); + var directoryPath = PathUtils.Combine(packagesPath, name); + + //if (IsCmsDownload(pathManager, osArchitecture, version)) + //{ + // return directoryPath; + //} var directoryNames = DirectoryUtils.GetDirectoryNames(packagesPath); foreach (var directoryName in directoryNames.Where(directoryName => StringUtils.StartsWithIgnoreCase(directoryName, "sscms-"))) @@ -71,14 +71,13 @@ public static void DownloadCms(IPathManager pathManager, string version) DirectoryUtils.DeleteDirectoryIfExists(PathUtils.Combine(packagesPath, directoryName)); } - var directoryPath = PathUtils.Combine(packagesPath, name); DirectoryUtils.CreateDirectoryIfNotExists(directoryPath); - var filePath = PathUtils.Combine(directoryPath, $"{GetCmsDownloadName(version)}.zip"); + var filePath = PathUtils.Combine(packagesPath, $"{GetCmsDownloadName(osArchitecture, version)}.zip"); FileUtils.WriteText(filePath, string.Empty); using (var writer = File.OpenWrite(filePath)) { - var client = new RestClient(GetCmsDownloadUrl(version)); + var client = new RestClient(GetCmsDownloadUrl(osArchitecture, version)); var request = new RestRequest(); request.ResponseWriter = responseStream => { @@ -90,13 +89,17 @@ public static void DownloadCms(IPathManager pathManager, string version) client.DownloadData(request); } - ZipUtils.ExtractZip(filePath, directoryPath); + pathManager.ExtractZip(filePath, directoryPath); + + FileUtils.DeleteFileIfExists(filePath); + + return directoryPath; } - public static bool IsCmsDownload(IPathManager pathManager, string version) + public static bool IsCmsDownload(IPathManager pathManager, string osArchitecture, string version) { var packagesPath = pathManager.GetPackagesPath(); - var name = GetCmsDownloadName(version); + var name = GetCmsDownloadName(osArchitecture, version); var directoryPath = PathUtils.Combine(packagesPath, name); diff --git a/src/SSCMS.Core/Plugins/Extensions/PluginApplicationBuilderExtensions.cs b/src/SSCMS.Core/Plugins/Extensions/PluginApplicationBuilderExtensions.cs index 8467c8c01..1c6f9f215 100644 --- a/src/SSCMS.Core/Plugins/Extensions/PluginApplicationBuilderExtensions.cs +++ b/src/SSCMS.Core/Plugins/Extensions/PluginApplicationBuilderExtensions.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Datory; @@ -9,6 +10,7 @@ using SSCMS.Configuration; using SSCMS.Models; using SSCMS.Plugins; +using SSCMS.Repositories; using SSCMS.Services; using SSCMS.Utils; @@ -17,7 +19,7 @@ namespace SSCMS.Core.Plugins.Extensions public static class PluginApplicationBuilderExtensions { public static async Task UsePluginsAsync(this IApplicationBuilder app, ISettingsManager settingsManager, - IPluginManager pluginManager) + IPluginManager pluginManager, IErrorLogRepository errorLogRepository) { var logger = app.ApplicationServices.GetService() .CreateLogger(); @@ -38,26 +40,26 @@ public static async Task UsePluginsAsync(this IApplicationBuilder app, ISettings }); } - var instances = pluginManager.GetExtensions(); - if (instances != null) + var configures = pluginManager.GetExtensions(); + if (configures != null) { - foreach (var pluginConfigure in instances) + foreach (var configure in configures) { - pluginConfigure.Configure(app); + configure.Configure(app); } } var database = settingsManager.Database; - var tables = pluginManager.GetTables(); + var tables = settingsManager.GetTables(); foreach (var table in tables.Where(table => !string.IsNullOrEmpty(table.Id))) { List columns; - if (table.Type == TableType.Custom) + if (StringUtils.EqualsIgnoreCase(table.Type, Types.TableTypes.Custom)) { columns = table.Columns; } - else if (table.Type == TableType.Content) + else if (StringUtils.EqualsIgnoreCase(table.Type, Types.TableTypes.Content)) { columns = database.GetTableColumns(null); columns.AddRange(database.GetTableColumns()); diff --git a/src/SSCMS.Core/Plugins/PackageMetadata.cs b/src/SSCMS.Core/Plugins/PackageMetadata.cs deleted file mode 100644 index 1cb78c5dd..000000000 --- a/src/SSCMS.Core/Plugins/PackageMetadata.cs +++ /dev/null @@ -1,268 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using NuGet.Packaging; -using NuGet.Versioning; -using SSCMS.Services; -using SSCMS.Utils; - -namespace SSCMS.Core.Plugins -{ - public class PackageMetadata : IPackageMetadata - { - private readonly Dictionary _metadata; - private readonly IReadOnlyCollection _dependencyGroups; - private readonly IReadOnlyCollection _frameworkReferenceGroups; - private readonly IReadOnlyCollection _packageTypes; - - public PackageMetadata(string directoryName) - { - PluginId = directoryName; - Name = directoryName; - IconUrl = "https://www.siteserver.cn/assets/images/favicon.png"; - Version = "0.0.0"; - } - - public PackageMetadata(IOldPlugin plugin) - { - PluginId = plugin.PluginId; - Version = plugin.Version; - IconUrl = plugin.IconUrl; - ProjectUrl = plugin.ProjectUrl; - LicenseUrl = plugin.LicenseUrl; - Copyright = plugin.Copyright; - Description = plugin.Description; - ReleaseNotes = plugin.ReleaseNotes; - Name = plugin.Name; - Tags = plugin.Tags; - Language = plugin.Language; - Owners = plugin.Owners; - Authors = plugin.Authors; - } - - public PackageMetadata( - Dictionary metadata, - IEnumerable dependencyGroups, - IEnumerable frameworkGroups, - IEnumerable packageTypes, - NuGetVersion minClientVersion) - { - _metadata = new Dictionary(metadata, StringComparer.OrdinalIgnoreCase); - _dependencyGroups = dependencyGroups.ToList().AsReadOnly(); - _frameworkReferenceGroups = frameworkGroups.ToList().AsReadOnly(); - _packageTypes = packageTypes.ToList().AsReadOnly(); - - SetPropertiesFromMetadata(); - MinClientVersion = minClientVersion; - } - - private void SetPropertiesFromMetadata() - { - PluginId = GetValue(PackageMetadataStrings.Id, string.Empty); - Version = GetValue(PackageMetadataStrings.Version, string.Empty); - IconUrl = GetValue(PackageMetadataStrings.IconUrl, string.Empty); - ProjectUrl = GetValue(PackageMetadataStrings.ProjectUrl, string.Empty); - LicenseUrl = GetValue(PackageMetadataStrings.LicenseUrl, string.Empty); - Copyright = GetValue(PackageMetadataStrings.Copyright, string.Empty); - Description = GetValue(PackageMetadataStrings.Description, string.Empty); - ReleaseNotes = GetValue(PackageMetadataStrings.ReleaseNotes, string.Empty); - Name = GetValue(PackageMetadataStrings.Name, string.Empty); - Tags = GetValue(PackageMetadataStrings.Tags, string.Empty); - Language = GetValue(PackageMetadataStrings.Language, string.Empty); - Owners = GetValue(PackageMetadataStrings.Owners, string.Empty); - Authors = GetValue(PackageMetadataStrings.Authors, string.Empty); - - if (Version.IndexOf('.') < 0) - { - throw new FormatException($"版本号不正确:{Version}"); - } - - NuGetVersion nugetVersion; - if (NuGetVersion.TryParse(Version, out nugetVersion)) - { - NuGetVersion = nugetVersion; - } - } - - public string PluginId { get; private set; } - public string Version { get; private set; } - public string IconUrl { get; private set; } - public string ProjectUrl { get; private set; } - public string LicenseUrl { get; private set; } - public string Copyright { get; private set; } - public string Description { get; private set; } - public string ReleaseNotes { get; private set; } - public string Name { get; private set; } - public string Tags { get; private set; } - public string Authors { get; private set; } - public string Owners { get; private set; } - public string Language { get; private set; } - - public NuGetVersion NuGetVersion { get; private set; } - public NuGetVersion MinClientVersion { get; set; } - - public string GetValueFromMetadata(string key) - { - return GetValue(key, string.Empty); - } - - public IReadOnlyCollection GetDependencyGroups() - { - return _dependencyGroups; - } - - public IReadOnlyCollection GetFrameworkReferenceGroups() - { - return _frameworkReferenceGroups; - } - - public IReadOnlyCollection GetPackageTypes() - { - return _packageTypes; - } - - private string GetValue(string key, string alternateValue) - { - string value; - if (_metadata.TryGetValue(key, out value)) - { - return value; - } - - return alternateValue; - } - - private bool GetValue(string key, bool alternateValue) - { - var value = GetValue(key, alternateValue.ToString()); - - bool result; - if (bool.TryParse(value, out result)) - { - return result; - } - - return alternateValue; - } - - private Uri GetValue(string key, Uri alternateValue) - { - var value = GetValue(key, string.Empty); - if (!string.IsNullOrEmpty(value)) - { - Uri result; - if (Uri.TryCreate(value, UriKind.Absolute, out result)) - { - return result; - } - } - - return alternateValue; - } - - /// - /// Gets package metadata from a the provided instance. - /// - /// The - public static PackageMetadata FromNuspecReader(NuspecReader nuspecReader) - { - return new PackageMetadata( - nuspecReader.GetMetadata().ToDictionary(kvp => kvp.Key, kvp => kvp.Value), - nuspecReader.GetDependencyGroups(true), - nuspecReader.GetFrameworkAssemblyGroups(), - nuspecReader.GetPackageTypes(), - nuspecReader.GetMinClientVersion() - ); - } - - public static PackageMetadata GetPackageMetadataFromPackages(IPathManager pathManager, string directoryName, out string nuspecPath, out string dllDirectoryPath, out string errorMessage) - { - nuspecPath = string.Empty; - dllDirectoryPath = string.Empty; - errorMessage = string.Empty; - - var directoryPath = pathManager.GetPackagesPath(directoryName); - - foreach (var filePath in DirectoryUtils.GetFilePaths(directoryPath)) - { - if (StringUtils.EqualsIgnoreCase(Path.GetExtension(filePath), ".zip")) - { - nuspecPath = filePath; - break; - } - } - - if (string.IsNullOrEmpty(nuspecPath)) - { - errorMessage = "配置文件不存在"; - return null; - } - - PackageMetadata metadata; - try - { - metadata = GetPackageMetadata(nuspecPath); - } - catch (Exception ex) - { - errorMessage = ex.Message; - return null; - } - - var packageId = metadata.PluginId; - - if (string.IsNullOrEmpty(packageId)) - { - errorMessage = $"配置文件 {nuspecPath} 不正确"; - return null; - } - - dllDirectoryPath = FindDllDirectoryPath(directoryPath); - - //if (!FileUtils.IsFileExists(PathUtils.Combine(dllDirectoryPath, packageId + ".dll"))) - //{ - // errorMessage = $"插件可执行文件 {packageId}.dll 不存在"; - // return null; - //} - - return metadata; - } - - //https://docs.microsoft.com/en-us/nuget/schema/target-frameworks#supported-frameworks - private static string FindDllDirectoryPath(string packageDirectoryPath) - { - var dllDirectoryPath = string.Empty; - - foreach (var dirName in DirectoryUtils.GetDirectoryNames(PathUtils.Combine(packageDirectoryPath, "lib"))) - { - if (StringUtils.StartsWithIgnoreCase(dirName, "net45") || - StringUtils.StartsWithIgnoreCase(dirName, "net451") || - StringUtils.StartsWithIgnoreCase(dirName, "net452") || - StringUtils.StartsWithIgnoreCase(dirName, "net46") || - StringUtils.StartsWithIgnoreCase(dirName, "net461") || - StringUtils.StartsWithIgnoreCase(dirName, "net462")) - { - dllDirectoryPath = PathUtils.Combine(packageDirectoryPath, "lib", dirName); - break; - } - } - if (string.IsNullOrEmpty(dllDirectoryPath)) - { - dllDirectoryPath = PathUtils.Combine(packageDirectoryPath, "lib"); - } - - return dllDirectoryPath; - } - - private static PackageMetadata GetPackageMetadata(string configPath) - { - var nuspecReader = new NuspecReader(configPath); - - var rawMetadata = nuspecReader.GetMetadata(); - if (rawMetadata == null || !rawMetadata.Any()) return null; - - return PackageMetadata.FromNuspecReader(nuspecReader); - } - } -} diff --git a/src/SSCMS.Core/Plugins/PackageMetadataStrings.cs b/src/SSCMS.Core/Plugins/PackageMetadataStrings.cs deleted file mode 100644 index 221ba88d1..000000000 --- a/src/SSCMS.Core/Plugins/PackageMetadataStrings.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace SSCMS.Core.Plugins -{ - public static class PackageMetadataStrings - { - public const string Id = "id"; - public const string Version = "version"; - public const string Authors = "authors"; - public const string Copyright = "copyright"; - public const string Description = "description"; - public const string IconUrl = "iconUrl"; - public const string Language = "language"; - public const string LicenseUrl = "licenseUrl"; - public const string Owners = "owners"; - public const string ProjectUrl = "projectUrl"; - public const string ReleaseNotes = "releaseNotes"; - public const string Tags = "tags"; - public const string Name = "name"; - } -} diff --git a/src/SSCMS.Core/Plugins/Plugin.cs b/src/SSCMS.Core/Plugins/Plugin.cs index 67dd89e93..7818dfb3d 100644 --- a/src/SSCMS.Core/Plugins/Plugin.cs +++ b/src/SSCMS.Core/Plugins/Plugin.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Reflection; using Microsoft.Extensions.Configuration; +using SSCMS.Configuration; using SSCMS.Plugins; using SSCMS.Utils; @@ -14,7 +15,7 @@ public class Plugin : IPlugin public Plugin(string folderPath, bool reloadOnChange) { ContentRootPath = folderPath; - WebRootPath = PathUtils.Combine(folderPath, "wwwroot"); + WebRootPath = PathUtils.Combine(folderPath, Constants.WwwrootDirectory); var builder = new ConfigurationBuilder() .SetBasePath(folderPath) .AddJsonFile(Constants.PackageFileName, optional: false, reloadOnChange: reloadOnChange); @@ -25,10 +26,8 @@ public Plugin(string folderPath, bool reloadOnChange) Configuration = builder.Build(); } - public (bool, string) LoadAssembly() + public string GetAssemblyPath() { - if (string.IsNullOrEmpty(Main)) return (true, string.Empty); - string assemblyPath; if (FileUtils.IsFileExists(PathUtils.Combine(ContentRootPath, Output, Main))) { @@ -43,6 +42,15 @@ public Plugin(string folderPath, bool reloadOnChange) assemblyPath = Directory.GetFiles(ContentRootPath, Main, SearchOption.AllDirectories).FirstOrDefault(); } + return assemblyPath; + } + + public (bool, string) LoadAssembly() + { + if (string.IsNullOrEmpty(Main)) return (true, string.Empty); + + var assemblyPath = GetAssemblyPath(); + if (string.IsNullOrEmpty(assemblyPath)) return (false, $"{Main}可执行文件不存在"); try @@ -83,11 +91,56 @@ public Plugin(string folderPath, bool reloadOnChange) public string Homepage => Configuration[nameof(Homepage)]; public string Output => Configuration[nameof(Output)]; public string Main => Configuration[nameof(Main)]; + public bool ApplyToSites => Configuration.GetValue(nameof(ApplyToSites), true); + public bool ApplyToChannels => Configuration.GetValue(nameof(ApplyToChannels), false); public bool Disabled => Configuration.GetValue(nameof(Disabled)); + public bool AllSites => Configuration.GetValue(nameof(AllSites), true); + public IEnumerable SiteIds => Configuration.GetSection(nameof(SiteIds)).Get(); + public IEnumerable SiteConfigs => Configuration.GetSection(nameof(SiteConfigs)).Get(); + public IEnumerable Tables => Configuration.GetSection(nameof(Tables)).Get(); + public bool Success { get; set; } public string ErrorMessage { get; set; } public int Taxis => Configuration.GetValue(nameof(Taxis)); + + public List GetMenus() + { + var section = Configuration.GetSection("extensions:menus"); + return GetMenus(section); + } + + private List GetMenus(IConfigurationSection section) + { + var menus = new List(); + if (section.Exists()) + { + var children = section.GetChildren(); + if (children != null) + { + foreach (var child in children) + { + var menu = child.Get(); + var childSection = child.GetSection("menus"); + + menus.Add(new Menu + { + Id = child.Key, + Text = menu.Text, + Type = menu.Type, + IconClass = menu.IconClass, + Link = menu.Link, + Target = menu.Target, + Permissions = menu.Permissions, + Order = menu.Order, + Children = GetMenus(childSection) + }); + } + } + } + + return menus.OrderByDescending(x => x.Order.HasValue).ThenBy(x => x.Order).ToList(); + } } } diff --git a/src/SSCMS.Core/Plugins/PluginStlParseContext.cs b/src/SSCMS.Core/Plugins/PluginStlParseContext.cs deleted file mode 100644 index c8b4832ba..000000000 --- a/src/SSCMS.Core/Plugins/PluginStlParseContext.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Specialized; -using SSCMS.Enums; -using SSCMS.Parse; - -namespace SSCMS.Core.Plugins -{ - public class PluginStlParseContext : IStlParseContext - { - public void Load(string stlOuterHtml, string stlInnerHtml, NameValueCollection stlAttributes, ParsePage pageInfo, ParseContext contextInfo) - { - SiteId = contextInfo.Site.Id; - ChannelId = contextInfo.ChannelId; - ContentId = contextInfo.ContentId; - TemplateType = pageInfo.Template.TemplateType; - TemplateId = pageInfo.Template.Id; - - HeadCodes = pageInfo.HeadCodes; - BodyCodes = pageInfo.BodyCodes; - FootCodes = pageInfo.FootCodes; - StlOuterHtml = stlOuterHtml; - StlInnerHtml = stlInnerHtml; - StlAttributes = stlAttributes; - - IsStlElement = !contextInfo.IsStlEntity; - PluginItems = pageInfo.PluginItems; - } - - public Dictionary PluginItems { get; private set; } - - public void Set(string key, T objectValue) - { - if (PluginItems != null && !string.IsNullOrEmpty(key)) - { - PluginItems[key] = objectValue; - } - } - - public T Get(string key) - { - object objectValue; - if (PluginItems.TryGetValue(key, out objectValue)) - { - if (objectValue is T) - { - return (T) objectValue; - } - } - - return default(T); - } - - public int SiteId { get; private set; } - - public int ChannelId { get; private set; } - - public int ContentId { get; private set; } - - public TemplateType TemplateType { get; private set; } - - public string FilePath { get; private set; } - - public int TemplateId { get; private set; } - - public SortedDictionary HeadCodes { get; private set; } - - public SortedDictionary BodyCodes { get; private set; } - - public SortedDictionary FootCodes { get; private set; } - - public string StlOuterHtml { get; private set; } - - public string StlInnerHtml { get; private set; } - - public NameValueCollection StlAttributes { get; private set; } - - public bool IsStlElement { get; private set; } - } -} diff --git a/src/SSCMS.Core/Plugins/PluginUtils.cs b/src/SSCMS.Core/Plugins/PluginUtils.cs index 011935381..689cc490d 100644 --- a/src/SSCMS.Core/Plugins/PluginUtils.cs +++ b/src/SSCMS.Core/Plugins/PluginUtils.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Semver; +using SSCMS.Configuration; using SSCMS.Plugins; using SSCMS.Utils; @@ -37,12 +38,29 @@ public static Assembly LoadAssembly(string assemblyPath) var dllPath = Path.GetDirectoryName(assemblyPath); var assemblyFiles = Directory.GetFiles(dllPath, "*.dll", SearchOption.TopDirectoryOnly); + var extensionType = typeof(IPluginExtension); foreach (var assemblyFile in assemblyFiles) { var assemblyName = Path.GetFileNameWithoutExtension(assemblyFile); if (assemblyNames.Any(x => StringUtils.EqualsIgnoreCase(x, assemblyName))) continue; + var isValidAssembly = false; + foreach (var exportedType in assembly.GetExportedTypes()) + { + if (extensionType.IsAssignableFrom(exportedType) && + exportedType.GetTypeInfo().IsClass) + { + isValidAssembly = true; + break; + } + } + + if (!isValidAssembly) + { + throw new Exception("未找到集成IPluginExtension接口的实现"); + } + AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyFile); assemblyNames.Add(assemblyName); } @@ -61,7 +79,7 @@ public static Assembly LoadAssembly(string assemblyPath) /// when the same type(s) is requested. /// /// Found implementations of the given type. - private static IEnumerable GetImplementations(IEnumerable assemblies, bool useCaching = false) + private static IEnumerable GetImplementations(IEnumerable assemblies, bool useCaching = true) { var type = typeof(T); @@ -102,7 +120,7 @@ private static IEnumerable GetImplementations(IEnumerable ass /// when the instance(s) of the same type(s) is requested. /// /// The instances of the found implementations of the given type. - public static IEnumerable GetInstances(IEnumerable plugins, IServiceProvider provider, bool useCaching = false) + public static IEnumerable GetInstances(IEnumerable plugins, IServiceProvider provider, bool useCaching = true) { var instances = new List(); diff --git a/src/SSCMS.Core/Repositories/AdministratorRepository.cs b/src/SSCMS.Core/Repositories/AdministratorRepository.cs index 9a69c6737..095e1d739 100644 --- a/src/SSCMS.Core/Repositories/AdministratorRepository.cs +++ b/src/SSCMS.Core/Repositories/AdministratorRepository.cs @@ -335,14 +335,16 @@ private string EncodePassword(string password, PasswordFormat passwordFormat, ou { passwordSalt = GenerateSalt(); - var des = new DesEncryptor - { - InputString = password, - EncryptKey = passwordSalt - }; - des.DesEncrypt(); + retVal = TranslateUtils.EncryptStringBySecretKey(password, passwordSalt); + + //var des = new DesEncryptor + //{ + // InputString = password, + // EncryptKey = passwordSalt + //}; + //des.DesEncrypt(); - retVal = des.OutString; + //retVal = des.OutString; } return retVal; } @@ -581,14 +583,16 @@ private static string DecodePassword(string password, PasswordFormat passwordFor } else if (passwordFormat == PasswordFormat.Encrypted) { - var des = new DesEncryptor - { - InputString = password, - DecryptKey = passwordSalt - }; - des.DesDecrypt(); + retVal = TranslateUtils.DecryptStringBySecretKey(password, passwordSalt); + + //var des = new DesEncryptor + //{ + // InputString = password, + // DecryptKey = passwordSalt + //}; + //des.DesDecrypt(); - retVal = des.OutString; + //retVal = des.OutString; } return retVal; } diff --git a/src/SSCMS.Core/Repositories/ChannelRepository.Cache.cs b/src/SSCMS.Core/Repositories/ChannelRepository.Cache.cs index b8e62d713..7570e2434 100644 --- a/src/SSCMS.Core/Repositories/ChannelRepository.Cache.cs +++ b/src/SSCMS.Core/Repositories/ChannelRepository.Cache.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using SSCMS.Configuration; -using SSCMS.Core.Utils; using SSCMS.Dto; using SSCMS.Enums; using SSCMS.Models; @@ -97,13 +95,15 @@ public async Task> GetCascadeAsync(Site site, IChannelSummary summa { extra = await func(summary); } + + if (extra == null) return null; + var cascade = new Cascade { Value = summary.Id, Label = summary.ChannelName, Children = await GetCascadeChildrenAsync(site, summary.Id, func) }; - if (extra == null) return cascade; var dict = TranslateUtils.ToDictionary(extra); foreach (var o in dict) @@ -124,7 +124,11 @@ public async Task>> GetCascadeChildrenAsync(Site site, int par if (cache == null) continue; if (cache.ParentId == parentId) { - list.Add(await GetCascadeAsync(site, cache, func)); + var cascade = await GetCascadeAsync(site, cache, func); + if (cascade != null) + { + list.Add(cascade); + } } } @@ -283,8 +287,8 @@ public async Task> GetChannelIndexNamesAsync(int siteId) private void GetParentIdsRecursive(List summaries, List list, int channelId) { - var summary = summaries.First(x => x.Id == channelId); - if (summary.ParentId > 0) + var summary = summaries.FirstOrDefault(x => x.Id == channelId); + if (summary != null && summary.ParentId > 0) { list.Add(summary.ParentId); GetParentIdsRecursive(summaries, list, summary.ParentId); @@ -396,8 +400,8 @@ public async Task> GetChannelIdsAsync(Channel channel, ScopeType scope public async Task IsExistsAsync(int channelId) { - var nodeInfo = await GetAsync(channelId); - return nodeInfo != null; + var channel = await GetAsync(channelId); + return channel != null; } public async Task GetTableNameAsync(Site site, int channelId) @@ -407,17 +411,23 @@ public async Task GetTableNameAsync(Site site, int channelId) public string GetTableName(Site site, IChannelSummary channel) { - return channel != null ? GetTableName(site, channel.ContentModelPluginId) : string.Empty; + return channel != null ? GetTableName(site, channel.TableName) : string.Empty; } - private string GetTableName(Site site, string contentModelPluginId) + private string GetTableName(Site site, string tableName) { - return string.IsNullOrEmpty(contentModelPluginId) ? site.TableName : contentModelPluginId; + if (string.IsNullOrEmpty(tableName)) + { + return site.TableName; + } + + var tableNames = _settingsManager.GetContentTableNames(); + return ListUtils.ContainsIgnoreCase(tableNames, tableName) ? tableName : site.TableName; } - public bool IsContentModelPlugin(Site site, Channel node) + public bool IsContentModelPlugin(Site site, Channel channel) { - return !string.IsNullOrEmpty(node.ContentModelPluginId); + return !string.IsNullOrEmpty(channel.TableName); } public async Task> GetGroupNamesAsync(int channelId) @@ -437,7 +447,7 @@ public async Task GetParentIdAsync(int siteId, int channelId) return retVal; } - private async Task GetParentsPathAsync(int siteId, int channelId) + private async Task GetParentsPathAsync(int channelId) { var retVal = string.Empty; var channel = await GetAsync(channelId); @@ -450,7 +460,7 @@ private async Task GetParentsPathAsync(int siteId, int channelId) public async Task GetTopLevelAsync(int siteId, int channelId) { - var parentsPath = await GetParentsPathAsync(siteId, channelId); + var parentsPath = await GetParentsPathAsync(channelId); return string.IsNullOrEmpty(parentsPath) ? 0 : parentsPath.Split(',').Length; } @@ -532,26 +542,6 @@ public async Task GetChannelNameNavigationAsync(int siteId, int currentC return ListUtils.ToString(channelNames, " > "); } - public async Task> GetInputStylesAsync(Site site, Channel channel) - { - var items = new List(); - - var tableName = GetTableName(site, channel); - var styleList = ColumnsManager.GetContentListStyles(await _tableStyleRepository.GetContentStylesAsync(channel, tableName)); - - foreach (var style in styleList) - { - var listitem = new InputStyle - { - DisplayName = style.DisplayName, - AttributeName = style.AttributeName - }; - items.Add(listitem); - } - - return items; - } - public async Task IsAncestorOrSelfAsync(int siteId, int parentId, int childId) { if (parentId == childId) diff --git a/src/SSCMS.Core/Repositories/ChannelRepository.Order.cs b/src/SSCMS.Core/Repositories/ChannelRepository.Order.cs index 216a098fb..a5763858e 100644 --- a/src/SSCMS.Core/Repositories/ChannelRepository.Order.cs +++ b/src/SSCMS.Core/Repositories/ChannelRepository.Order.cs @@ -26,33 +26,66 @@ private async Task GetMaxTaxisAsync(int siteId, int parentId) .Max(); } - public async Task UpdateTaxisDownAsync(int siteId, int channelId, int parentId, int taxis) + //public async Task UpdateTaxisDownAsync(int siteId, int channelId, int parentId, int taxis) + //{ + // var summaries = await GetSummariesAsync(siteId); + // var higher = summaries + // .Where(x => x.ParentId == parentId && x.Taxis > taxis && x.Id != channelId) + // .OrderBy(x => x.Taxis) + // .FirstOrDefault(); + + // if (higher != null) + // { + // await SetTaxisAsync(siteId, channelId, higher.Taxis); + // await SetTaxisAsync(siteId, higher.Id, taxis); + // } + //} + + //public async Task UpdateTaxisUpAsync(int siteId, int channelId, int parentId, int taxis) + //{ + // var summaries = await GetSummariesAsync(siteId); + + // var lower = summaries + // .Where(x => x.ParentId == parentId && x.Taxis < taxis && x.Id != channelId) + // .OrderByDescending(x => x.Taxis) + // .FirstOrDefault(); + + // if (lower != null) + // { + // await SetTaxisAsync(siteId, channelId, lower.Taxis); + // await SetTaxisAsync(siteId, lower.Id, taxis); + // } + //} + + public async Task UpdateTaxisAsync(int siteId, int parentId, int channelId, bool isUp) { var summaries = await GetSummariesAsync(siteId); - var higher = summaries - .Where(x => x.ParentId == parentId && x.Taxis > taxis && x.Id != channelId) + + var channelIds = summaries + .Where(x => x.ParentId == parentId) .OrderBy(x => x.Taxis) - .FirstOrDefault(); + .Select(x => x.Id) + .ToList(); + + var index = channelIds.IndexOf(channelId); - if (higher != null) + if (isUp && index == 0) return; + if (!isUp && index == channelIds.Count - 1) return; + + if (isUp) { - await SetTaxisAsync(siteId, channelId, higher.Taxis); - await SetTaxisAsync(siteId, higher.Id, taxis); + channelIds.Remove(channelId); + channelIds.Insert(index - 1, channelId); + } + else + { + channelIds.Remove(channelId); + channelIds.Insert(index + 1, channelId); } - } - - public async Task UpdateTaxisUpAsync(int siteId, int channelId, int parentId, int taxis) - { - var summaries = await GetSummariesAsync(siteId); - var lower = summaries - .Where(x => x.ParentId == parentId && x.Taxis < taxis && x.Id != channelId) - .OrderByDescending(x => x.Taxis) - .FirstOrDefault(); - if (lower != null) + for (var taxis = 1; taxis <= channelIds.Count; taxis++) { - await SetTaxisAsync(siteId, channelId, lower.Taxis); - await SetTaxisAsync(siteId, lower.Id, taxis); + await SetTaxisAsync(siteId, channelIds[taxis - 1], taxis); } } } diff --git a/src/SSCMS.Core/Repositories/ChannelRepository.cs b/src/SSCMS.Core/Repositories/ChannelRepository.cs index afaa292f5..b5c889ab5 100644 --- a/src/SSCMS.Core/Repositories/ChannelRepository.cs +++ b/src/SSCMS.Core/Repositories/ChannelRepository.cs @@ -17,13 +17,13 @@ namespace SSCMS.Core.Repositories public partial class ChannelRepository : IChannelRepository { private readonly Repository _repository; - private readonly ITableStyleRepository _tableStyleRepository; + private readonly ISettingsManager _settingsManager; private readonly ITemplateRepository _templateRepository; - public ChannelRepository(ISettingsManager settingsManager, ITableStyleRepository tableStyleRepository, ITemplateRepository templateRepository) + public ChannelRepository(ISettingsManager settingsManager, ITemplateRepository templateRepository) { _repository = new Repository(settingsManager.Database, settingsManager.Redis); - _tableStyleRepository = tableStyleRepository; + _settingsManager = settingsManager; _templateRepository = templateRepository; } @@ -82,7 +82,7 @@ await _repository.IncrementAsync(nameof(Channel.ChildrenCount), Q } } - public async Task InsertAsync(int siteId, int parentId, string channelName, string indexName, string contentModelPluginId, List contentRelatedPluginIds, int channelTemplateId, int contentTemplateId) + public async Task InsertAsync(int siteId, int parentId, string channelName, string indexName, string contentModelPluginId, int channelTemplateId, int contentTemplateId) { if (siteId > 0 && parentId == 0) return 0; @@ -96,7 +96,6 @@ public async Task InsertAsync(int siteId, int parentId, string channelName, ChannelName = channelName, IndexName = indexName, ContentModelPluginId = contentModelPluginId, - ContentRelatedPluginIds = contentRelatedPluginIds, AddDate = DateTime.Now, ChannelTemplateId = channelTemplateId > 0 ? channelTemplateId : defaultChannelTemplateEntity.Id, ContentTemplateId = contentTemplateId > 0 ? contentTemplateId : defaultContentTemplateEntity.Id @@ -173,6 +172,7 @@ public async Task DeleteAsync(Site site, int channelId, int adminId) var deletedNum = await _repository.DeleteAsync(Q .Where(nameof(Channel.SiteId), site.Id) .WhereIn(nameof(Channel.Id), idList) + .CachingRemove(GetListKey(site.Id)) ); if (channelEntity.ParentId != 0) @@ -180,6 +180,7 @@ public async Task DeleteAsync(Site site, int channelId, int adminId) await _repository.DecrementAsync(nameof(Channel.Taxis), Q .Where(nameof(Channel.SiteId), channelEntity.SiteId) .Where(nameof(Channel.Taxis), ">", channelEntity.Taxis) + .CachingRemove(GetListKey(site.Id)) , deletedNum); } @@ -187,6 +188,7 @@ await _repository.DecrementAsync(nameof(Channel.Taxis), Q { await _repository.DecrementAsync(nameof(Channel.ChildrenCount), Q .WhereIn(nameof(Channel.Id), ListUtils.GetIntList(channelEntity.ParentsPath)) + .CachingRemove(GetListKey(site.Id)) , deletedNum); } } @@ -196,6 +198,7 @@ public async Task DeleteAllAsync(int siteId) await _repository.DeleteAsync(Q .Where(nameof(Channel.SiteId), siteId) .OrWhere(nameof(Channel.Id), siteId) + .CachingRemove(GetListKey(siteId)) ); } diff --git a/src/SSCMS.Core/Repositories/ContentGroupRepository.cs b/src/SSCMS.Core/Repositories/ContentGroupRepository.cs index 01975cbcb..c456f654d 100644 --- a/src/SSCMS.Core/Repositories/ContentGroupRepository.cs +++ b/src/SSCMS.Core/Repositories/ContentGroupRepository.cs @@ -57,11 +57,11 @@ await _repository.DeleteAsync(Q public async Task UpdateTaxisDownAsync(int siteId, int groupId, int taxis) { - var higherGroup = await _repository.GetAsync(Q - .Where(nameof(ChannelGroup.SiteId), siteId) - .Where(nameof(ChannelGroup.Taxis), ">", taxis) - .WhereNot(nameof(ChannelGroup.Id), groupId) - .OrderBy(nameof(ChannelGroup.Taxis))); + var higherGroup = await _repository.GetAsync(Q + .Where(nameof(ContentGroup.SiteId), siteId) + .Where(nameof(ContentGroup.Taxis), ">", taxis) + .WhereNot(nameof(ContentGroup.Id), groupId) + .OrderBy(nameof(ContentGroup.Taxis))); if (higherGroup != null) { @@ -72,11 +72,11 @@ public async Task UpdateTaxisDownAsync(int siteId, int groupId, int taxis) public async Task UpdateTaxisUpAsync(int siteId, int groupId, int taxis) { - var lowerGroup = await _repository.GetAsync(Q - .Where(nameof(ChannelGroup.SiteId), siteId) - .Where(nameof(ChannelGroup.Taxis), "<", taxis) - .WhereNot(nameof(ChannelGroup.Id), groupId) - .OrderByDesc(nameof(ChannelGroup.Taxis))); + var lowerGroup = await _repository.GetAsync(Q + .Where(nameof(ContentGroup.SiteId), siteId) + .Where(nameof(ContentGroup.Taxis), "<", taxis) + .WhereNot(nameof(ContentGroup.Id), groupId) + .OrderByDesc(nameof(ContentGroup.Taxis))); if (lowerGroup != null) { @@ -88,8 +88,8 @@ public async Task UpdateTaxisUpAsync(int siteId, int groupId, int taxis) private async Task SetTaxisAsync(int groupId, int taxis) { await _repository.UpdateAsync(Q - .Set(nameof(ChannelGroup.Taxis), taxis) - .Where(nameof(ChannelGroup.Id), groupId) + .Set(nameof(ContentGroup.Taxis), taxis) + .Where(nameof(ContentGroup.Id), groupId) ); } diff --git a/src/SSCMS.Core/Repositories/ContentRepository.Delete.cs b/src/SSCMS.Core/Repositories/ContentRepository.Delete.cs index 6cee7b39c..613024240 100644 --- a/src/SSCMS.Core/Repositories/ContentRepository.Delete.cs +++ b/src/SSCMS.Core/Repositories/ContentRepository.Delete.cs @@ -5,13 +5,14 @@ using Datory; using SSCMS.Enums; using SSCMS.Models; +using SSCMS.Plugins; using SSCMS.Services; namespace SSCMS.Core.Repositories { public partial class ContentRepository { - public async Task RecycleContentsAsync(Site site, Channel channel, IEnumerable contentIdList, int adminId) + public async Task TrashContentsAsync(Site site, Channel channel, List contentIdList, int adminId) { if (contentIdList == null || !contentIdList.Any()) return; @@ -44,23 +45,50 @@ await repository.UpdateAsync( ); } - public async Task RecycleAllAsync(Site site, int channelId, int adminId) + public async Task TrashContentsAsync(Site site, int channelId, int adminId) { var channelIds = await _channelRepository.GetChannelIdsAsync(site.Id, channelId, ScopeType.All); foreach (var selectedId in channelIds) { var selected = await _channelRepository.GetAsync(selectedId); var contentIds = await GetContentIdsAsync(site, selected); - await RecycleContentsAsync(site, selected, contentIds, adminId); + await TrashContentsAsync(site, selected, contentIds, adminId); } } - /// - /// 回收站 - 删除选中 - /// - /// - /// - public async Task RecycleDeleteAsync(Site site, int channelId, string tableName, List contentIdList) + public async Task TrashContentAsync(Site site, Channel channel, int contentId, int adminId) + { + var repository = GetRepository(site, channel); + + var cacheKeys = new List + { + GetListKey(repository.TableName, site.Id, channel.Id), + GetEntityKey(repository.TableName, contentId) + }; + + var referenceSummaries = await GetReferenceIdListAsync(repository.TableName, new List + { + contentId + }); + if (referenceSummaries.Count > 0) + { + foreach (var referenceSummary in referenceSummaries) + { + await DeleteReferenceContentsAsync(site, referenceSummary); + } + } + + await repository.UpdateAsync( + GetQuery(site.Id, channel.Id) + .SetRaw("ChannelId = -ChannelId") + .Set(nameof(Content.LastEditAdminId), adminId) + .Where(nameof(Content.Id), contentId) + .CachingRemove(cacheKeys.ToArray()) + ); + } + + // 回收站 - 删除选中 + public async Task DeleteTrashAsync(Site site, int channelId, string tableName, List contentIdList, IPluginManager pluginManager) { if (contentIdList == null || contentIdList.Count == 0) return; @@ -81,16 +109,41 @@ await repository.DeleteAsync(Q .WhereIn(nameof(Content.Id), contentIdList) .CachingRemove(cacheKeys.ToArray()) ); + + var handlers = pluginManager.GetExtensions(); + foreach (var handler in handlers) + { + try + { + foreach (var contentId in contentIdList) + { + handler.OnDeleted(site.Id, channelId, contentId); + await handler.OnDeletedAsync(site.Id, channelId, contentId); + } + } + catch (Exception ex) + { + await _errorLogRepository.AddErrorLogAsync(ex); + } + } + + //foreach (var plugin in oldPluginManager.GetPlugins()) + //{ + // try + // { + // plugin.OnContentDeleteCompleted(new ContentEventArgs(site.Id, channel.Id, contentId)); + // } + // catch (Exception ex) + // { + // await _errorLogRepository.AddErrorLogAsync(plugin.PluginId, ex, nameof(plugin.OnContentDeleteCompleted)); + // } + //} } - /// - /// 回收站 - 删除全部 - /// - /// - /// - public async Task RecycleDeleteAllAsync(IOldPluginManager pluginManager, Site site) + // 回收站 - 删除全部 + public async Task DeleteTrashAsync(Site site, IPluginManager pluginManager) { - var tableNames = await _siteRepository.GetTableNamesAsync(pluginManager, site); + var tableNames = await _siteRepository.GetTableNamesAsync(site); foreach (var tableName in tableNames) { var repository = GetRepository(tableName); @@ -102,24 +155,24 @@ public async Task RecycleDeleteAllAsync(IOldPluginManager pluginManager, Site si .Distinct() ); - var cacheKeys = channelIds.Select(channelId => GetListKey(tableName, site.Id, channelId)); - - await repository.DeleteAsync(Q - .Where(nameof(Content.SiteId), site.Id) - .Where(nameof(Content.ChannelId), "<", 0) - .CachingRemove(cacheKeys.ToArray()) - ); + foreach (var channelId in channelIds) + { + var contentIds = await repository.GetAllAsync(Q + .Select(nameof(Content.Id)) + .Where(nameof(Content.SiteId), site.Id) + .Where(nameof(Content.ChannelId), channelId) + .Distinct() + ); + + await DeleteTrashAsync(site, channelId, tableName, contentIds, pluginManager); + } } } - /// - /// 回收站 - 恢复全部 - /// - /// - /// - public async Task RecycleRestoreAllAsync(IOldPluginManager pluginManager, Site site, int restoreChannelId) + // 回收站 - 恢复全部 + public async Task RestoreTrashAsync(Site site, int restoreChannelId) { - var tableNames = await _siteRepository.GetTableNamesAsync(pluginManager, site); + var tableNames = await _siteRepository.GetTableNamesAsync(site); foreach (var tableName in tableNames) { var repository = GetRepository(tableName); @@ -147,12 +200,8 @@ await repository.UpdateAsync(Q } } - /// - /// 回收站 - 恢复选中 - /// - /// - /// - public async Task RecycleRestoreAsync(Site site, int channelId, string tableName, List contentIdList, int restoreChannelId) + // 回收站 - 恢复选中 + public async Task RestoreTrashAsync(Site site, int channelId, string tableName, List contentIdList, int restoreChannelId) { if (contentIdList == null || contentIdList.Count == 0) return; @@ -174,30 +223,6 @@ await repository.UpdateAsync(Q ); } - public async Task DeleteAsync(IOldPluginManager pluginManager, Site site, Channel channel, int contentId) - { - if (site == null || channel == null || contentId <= 0) return; - - var repository = GetRepository(site, channel); - - await repository.DeleteAsync(contentId, Q - .CachingRemove(GetEntityKey(repository.TableName, contentId)) - .CachingRemove(GetListKey(repository.TableName, site.Id, channel.Id)) - ); - - foreach (var plugin in pluginManager.GetPlugins()) - { - try - { - plugin.OnContentDeleteCompleted(new ContentEventArgs(site.Id, channel.Id, contentId)); - } - catch (Exception ex) - { - await _errorLogRepository.AddErrorLogAsync(plugin.PluginId, ex, nameof(plugin.OnContentDeleteCompleted)); - } - } - } - private async Task DeleteReferenceContentsAsync(Site site, ContentSummary summary) { var channel = await _channelRepository.GetAsync(summary.ChannelId); diff --git a/src/SSCMS.Core/Repositories/ContentRepository.Get.cs b/src/SSCMS.Core/Repositories/ContentRepository.Get.cs index 7e0351bbf..8a98ec93a 100644 --- a/src/SSCMS.Core/Repositories/ContentRepository.Get.cs +++ b/src/SSCMS.Core/Repositories/ContentRepository.Get.cs @@ -289,7 +289,7 @@ public async Task GetWhereStringByStlSearchAsync(IDatabaseManager databa foreach (string key in form.Keys) { - if (excludeAttributes.Contains(key.ToLower())) continue; + if (ListUtils.ContainsIgnoreCase(excludeAttributes, key)) continue; if (string.IsNullOrEmpty(form[key])) continue; var value = StringUtils.Trim(form[key]); diff --git a/src/SSCMS.Core/Repositories/ContentRepository.Insert.cs b/src/SSCMS.Core/Repositories/ContentRepository.Insert.cs index 0e0ded639..4f47d0ffc 100644 --- a/src/SSCMS.Core/Repositories/ContentRepository.Insert.cs +++ b/src/SSCMS.Core/Repositories/ContentRepository.Insert.cs @@ -121,6 +121,8 @@ public async Task InsertWithTaxisAsync(Site site, Channel channel, Content else { await repository.InsertAsync(content, Q.CachingRemove(GetListKey(tableName, content.SiteId, content.ChannelId))); + + await _statRepository.AddCountAsync(StatType.ContentAdd, content.SiteId); } return content.Id; diff --git a/src/SSCMS.Core/Repositories/ContentRepository.Parser.cs b/src/SSCMS.Core/Repositories/ContentRepository.Parser.cs index 08bdfd496..ee6c7aab5 100644 --- a/src/SSCMS.Core/Repositories/ContentRepository.Parser.cs +++ b/src/SSCMS.Core/Repositories/ContentRepository.Parser.cs @@ -146,7 +146,7 @@ private async Task> GetStlDataSourceCheckedAsync(IDatabaseM return startNum <= 1 ? GetStlDataSourceByContentNumAndWhereString(tableName, totalNum, sqlWhereString, orderByString) : GetStlDataSourceByStartNum(tableName, startNum, totalNum, sqlWhereString, orderByString); } - private async Task> GetContentsDataSourceAsync(IDatabaseManager databaseManager, IOldPluginManager pluginManager, Site site, int channelId, int contentId, string groupContent, string groupContentNot, string tags, bool isImageExists, bool isImage, bool isVideoExists, bool isVideo, bool isFileExists, bool isFile, bool isRelatedContents, int startNum, int totalNum, string orderByString, bool isTopExists, bool isTop, bool isRecommendExists, bool isRecommend, bool isHotExists, bool isHot, bool isColorExists, bool isColor, ScopeType scopeType, string groupChannel, string groupChannelNot, NameValueCollection others) + private async Task> GetContentsDataSourceAsync(IDatabaseManager databaseManager, Site site, int channelId, int contentId, string groupContent, string groupContentNot, string tags, bool isImageExists, bool isImage, bool isVideoExists, bool isVideo, bool isFileExists, bool isFile, bool isRelatedContents, int startNum, int totalNum, string orderByString, bool isTopExists, bool isTop, bool isRecommendExists, bool isRecommend, bool isHotExists, bool isHot, bool isColorExists, bool isColor, ScopeType scopeType, string groupChannel, string groupChannelNot, NameValueCollection others) { if (!await _channelRepository.IsExistsAsync(channelId)) return null; @@ -159,10 +159,7 @@ private async Task> GetContentsDataSourceAsync(IDatabaseMan where = $"ID <> {contentId}"; } - var sqlWhereString = pluginManager.IsExists(channel.ContentModelPluginId) - ? GetStlWhereString(site.Id, groupContent, groupContentNot, - tags, isTopExists, isTop, where) - : GetStlWhereString(site.Id, groupContent, + var sqlWhereString = GetStlWhereString(site.Id, groupContent, groupContentNot, tags, isImageExists, isImage, isVideoExists, isVideo, isFileExists, isFile, isTopExists, isTop, isRecommendExists, isRecommend, isHotExists, isHot, isColorExists, isColor, where); @@ -171,9 +168,9 @@ private async Task> GetContentsDataSourceAsync(IDatabaseMan return await GetStlDataSourceCheckedAsync(databaseManager, channelIdList, tableName, startNum, totalNum, orderByString, sqlWhereString, others); } - public async Task> GetSummariesAsync(IDatabaseManager databaseManager, IOldPluginManager pluginManager, Site site, int channelId, int contentId, string groupContent, string groupContentNot, string tags, bool isImageExists, bool isImage, bool isVideoExists, bool isVideo, bool isFileExists, bool isFile, bool isRelatedContents, int startNum, int totalNum, string orderByString, bool isTopExists, bool isTop, bool isRecommendExists, bool isRecommend, bool isHotExists, bool isHot, bool isColorExists, bool isColor, ScopeType scopeType, string groupChannel, string groupChannelNot, NameValueCollection others) + public async Task> GetSummariesAsync(IDatabaseManager databaseManager, Site site, int channelId, int contentId, string groupContent, string groupContentNot, string tags, bool isImageExists, bool isImage, bool isVideoExists, bool isVideo, bool isFileExists, bool isFile, bool isRelatedContents, int startNum, int totalNum, string orderByString, bool isTopExists, bool isTop, bool isRecommendExists, bool isRecommend, bool isHotExists, bool isHot, bool isColorExists, bool isColor, ScopeType scopeType, string groupChannel, string groupChannelNot, NameValueCollection others) { - var dataSource = await GetContentsDataSourceAsync(databaseManager, pluginManager, site, channelId, contentId, groupContent, groupContentNot, tags, + var dataSource = await GetContentsDataSourceAsync(databaseManager, site, channelId, contentId, groupContent, groupContentNot, tags, isImageExists, isImage, isVideoExists, isVideo, isFileExists, isFile, isRelatedContents, startNum, totalNum, orderByString, isTopExists, isTop, isRecommendExists, isRecommend, isHotExists, isHot, isColorExists, isColor, scopeType, groupChannel, groupChannelNot, others); @@ -195,7 +192,7 @@ public async Task> GetSummariesAsync(IDatabaseManager datab //return list; } - public async Task>> ParserGetContentsDataSourceAsync(Site site, int channelId, int contentId, string groupContent, string groupContentNot, string tags, bool isImageExists, bool isImage, bool isVideoExists, bool isVideo, bool isFileExists, bool isFile, bool isRelatedContents, int startNum, int totalNum, TaxisType taxisType, bool isTopExists, bool isTop, bool isRecommendExists, bool isRecommend, bool isHotExists, bool isHot, bool isColorExists, bool isColor, ScopeType scopeType, string groupChannel, string groupChannelNot, NameValueCollection others) + public async Task>> ParserGetContentsDataSourceAsync(Site site, int channelId, int contentId, string groupContent, string groupContentNot, string tags, bool isImageExists, bool isImage, bool isVideoExists, bool isVideo, bool isFileExists, bool isFile, bool isRelatedContents, int startNum, int totalNum, TaxisType taxisType, string where, bool isTopExists, bool isTop, bool isRecommendExists, bool isRecommend, bool isHotExists, bool isHot, bool isColorExists, bool isColor, ScopeType scopeType, string groupChannel, string groupChannelNot, NameValueCollection others) { if (!await _channelRepository.IsExistsAsync(channelId)) return null; @@ -434,6 +431,11 @@ public async Task>> ParserGetContentsDataSourceA ParserOrderQuery(query, taxisType); + if (!string.IsNullOrEmpty(where)) + { + query.WhereRaw(where); + } + var summaries = await repository.GetAllAsync(query); if (startNum > 1 && totalNum > 0) diff --git a/src/SSCMS.Core/Repositories/ContentRepository.StlCache.cs b/src/SSCMS.Core/Repositories/ContentRepository.StlCache.cs index 6dccdc397..562b9c46b 100644 --- a/src/SSCMS.Core/Repositories/ContentRepository.StlCache.cs +++ b/src/SSCMS.Core/Repositories/ContentRepository.StlCache.cs @@ -39,22 +39,22 @@ public string GetStlWhereString(int siteId, string group, string groupNot, strin if (isTopExists) { - whereBuilder.Append($" AND {nameof(Content.Top)} = {isTop.ToString().ToLower()} "); + whereBuilder.Append($" AND {nameof(Content.Top)} = {StringUtils.ToLower(isTop.ToString())} "); } if (isRecommendExists) { - whereBuilder.Append($" AND {nameof(Content.Recommend)} = {isRecommend.ToString().ToLower()} "); + whereBuilder.Append($" AND {nameof(Content.Recommend)} = {StringUtils.ToLower(isRecommend.ToString())} "); } if (isHotExists) { - whereBuilder.Append($" AND {nameof(Content.Hot)} = {isHot.ToString().ToLower()} "); + whereBuilder.Append($" AND {nameof(Content.Hot)} = {StringUtils.ToLower(isHot.ToString())} "); } if (isColorExists) { - whereBuilder.Append($" AND {nameof(Content.Color)} = {isColor.ToString().ToLower()} "); + whereBuilder.Append($" AND {nameof(Content.Color)} = {StringUtils.ToLower(isColor.ToString())} "); } var databaseType = _settingsManager.Database.DatabaseType; @@ -151,22 +151,22 @@ public string GetStlWhereStringBySearch(string group, string groupNot, bool isIm if (isTopExists) { - whereBuilder.Append($" AND {nameof(Content.Top)} = {isTop.ToString().ToLower()} "); + whereBuilder.Append($" AND {nameof(Content.Top)} = {StringUtils.ToLower(isTop.ToString())} "); } if (isRecommendExists) { - whereBuilder.Append($" AND {nameof(Content.Recommend)} = {isRecommend.ToString().ToLower()} "); + whereBuilder.Append($" AND {nameof(Content.Recommend)} = {StringUtils.ToLower(isRecommend.ToString())} "); } if (isHotExists) { - whereBuilder.Append($" AND {nameof(Content.Hot)} = {isHot.ToString().ToLower()} "); + whereBuilder.Append($" AND {nameof(Content.Hot)} = {StringUtils.ToLower(isHot.ToString())} "); } if (isColorExists) { - whereBuilder.Append($" AND {nameof(Content.Color)} = {isColor.ToString().ToLower()} "); + whereBuilder.Append($" AND {nameof(Content.Color)} = {StringUtils.ToLower(isColor.ToString())} "); } var databaseType = _settingsManager.Database.DatabaseType; @@ -336,7 +336,7 @@ public int GetContentId(string tableName, int channelId, bool isCheckedOnly, str var whereString = $"WHERE {nameof(Content.ChannelId)} = {channelId}"; if (isCheckedOnly) { - whereString += $" AND {nameof(Content.Checked)} = {true.ToString().ToLower()}"; + whereString += $" AND {nameof(Content.Checked)} = {StringUtils.ToLower(true.ToString())}"; } var sqlString = SqlUtils.ToTopSqlString(Database.DatabaseType, tableName, "Id", whereString, orderByString, 1); @@ -372,11 +372,6 @@ public async Task GetSequenceAsync(string tableName, int siteId, int channe .WhereTrue(nameof(Content.Checked)) .Where(nameof(Content.Taxis), "<", taxis) ) + 1; - - //var sqlString = - // $"SELECT COUNT(*) FROM {tableName} WHERE {ContentAttribute.ChannelId} = {channelId} AND {nameof(Content.Checked)} = {true.ToString().ToLower()} AND Taxis < (SELECT Taxis FROM {tableName} WHERE Id = {contentId}) AND {ContentAttribute.SourceId} != {SourceManager.Preview}"; - - //return _databaseRepository.GetIntResult(sqlString) + 1; } private List GetStlDataSourceByContentNumAndWhereString(string tableName, int totalNum, string whereString, string orderByString) @@ -411,12 +406,6 @@ public async Task GetCountCheckedImageAsync(Site site, Channel channel) .WhereTrue(nameof(Content.Checked)) .WhereNotNullOrEmpty(nameof(Content.ImageUrl)) ) + 1; - - //var tableName = await _siteRepository.GetTableNameAsync(siteId); - //var sqlString = - // $"SELECT COUNT(*) FROM {tableName} WHERE {ContentAttribute.ChannelId} = {channelId} AND {ContentAttribute.ImageUrl} != '' AND {nameof(Content.Checked)} = {true.ToString().ToLower()} AND {ContentAttribute.SourceId} != {SourceManager.Preview}"; - - //return _databaseRepository.GetIntResult(sqlString); } } } diff --git a/src/SSCMS.Core/Repositories/ContentRepository.Update.cs b/src/SSCMS.Core/Repositories/ContentRepository.Update.cs index 7a4d43b58..d49c2fd0a 100644 --- a/src/SSCMS.Core/Repositories/ContentRepository.Update.cs +++ b/src/SSCMS.Core/Repositories/ContentRepository.Update.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using Datory; using SSCMS.Core.Utils; +using SSCMS.Enums; using SSCMS.Models; using SSCMS.Services; @@ -43,13 +44,15 @@ await repository.UpdateAsync(content, Q .CachingRemove(GetListKey(repository.TableName, content.SiteId, content.ChannelId)) .CachingRemove(GetEntityKey(repository.TableName, content.Id)) ); + + await _statRepository.AddCountAsync(StatType.ContentEdit, content.SiteId); } - public async Task SetAutoPageContentToSiteAsync(IOldPluginManager pluginManager, Site site) + public async Task SetAutoPageContentToSiteAsync(Site site) { if (!site.IsAutoPageInTextEditor) return; - var tableNames = await _siteRepository.GetAllTableNamesAsync(pluginManager); + var tableNames = await _siteRepository.GetAllTableNamesAsync(); foreach (var tableName in tableNames) { var repository = GetRepository(tableName); diff --git a/src/SSCMS.Core/Repositories/ContentRepository.cs b/src/SSCMS.Core/Repositories/ContentRepository.cs index 6196edb62..5c9d987e9 100644 --- a/src/SSCMS.Core/Repositories/ContentRepository.cs +++ b/src/SSCMS.Core/Repositories/ContentRepository.cs @@ -13,15 +13,17 @@ public partial class ContentRepository : IContentRepository private readonly IChannelRepository _channelRepository; private readonly ISiteRepository _siteRepository; private readonly IErrorLogRepository _errorLogRepository; + private readonly IStatRepository _statRepository; private readonly Repository _repository; - public ContentRepository(ISettingsManager settingsManager, IAdministratorRepository administratorRepository, IChannelRepository channelRepository, ISiteRepository siteRepository, IErrorLogRepository errorLogRepository) + public ContentRepository(ISettingsManager settingsManager, IAdministratorRepository administratorRepository, IChannelRepository channelRepository, ISiteRepository siteRepository, IErrorLogRepository errorLogRepository, IStatRepository statRepository) { _settingsManager = settingsManager; _administratorRepository = administratorRepository; _channelRepository = channelRepository; _siteRepository = siteRepository; _errorLogRepository = errorLogRepository; + _statRepository = statRepository; _repository = new Repository(settingsManager.Database, settingsManager.Redis); } diff --git a/src/SSCMS.Core/Repositories/ContentTagRepository.Cache.cs b/src/SSCMS.Core/Repositories/ContentTagRepository.Cache.cs deleted file mode 100644 index 4674e5f10..000000000 --- a/src/SSCMS.Core/Repositories/ContentTagRepository.Cache.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Datory; -using SSCMS.Core.Utils; -using SSCMS.Models; - -namespace SSCMS.Core.Repositories -{ - public partial class ContentTagRepository - { - private string GetCacheKey(int siteId) - { - return CacheUtils.GetListKey(TableName, siteId); - } - - public async Task> GetTagNamesAsync(int siteId) - { - return await _repository.GetAllAsync(Q - .Select(nameof(ContentTag.TagName)) - .Where(nameof(ContentTag.SiteId), siteId) - .WhereNotNull(nameof(ContentTag.TagName)) - .WhereNot(nameof(ContentTag.TagName), string.Empty) - .Distinct() - .OrderBy(nameof(ContentTag.TagName)) - .CachingGet(GetCacheKey(siteId)) - ); - } - } -} \ No newline at end of file diff --git a/src/SSCMS.Core/Repositories/ContentTagRepository.cs b/src/SSCMS.Core/Repositories/ContentTagRepository.cs index 643c1edf4..9af4cd3c8 100644 --- a/src/SSCMS.Core/Repositories/ContentTagRepository.cs +++ b/src/SSCMS.Core/Repositories/ContentTagRepository.cs @@ -1,13 +1,18 @@ +using System; +using System.Collections; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Datory; +using SSCMS.Core.Utils; using SSCMS.Models; using SSCMS.Repositories; using SSCMS.Services; +using SSCMS.Utils; namespace SSCMS.Core.Repositories { - public partial class ContentTagRepository : IContentTagRepository + public class ContentTagRepository : IContentTagRepository { private readonly Repository _repository; @@ -22,6 +27,13 @@ public ContentTagRepository(ISettingsManager settingsManager) public List TableColumns => _repository.TableColumns; + public async Task InsertAsync(ContentTag tag) + { + await _repository.InsertAsync(tag, Q + .CachingRemove(GetCacheKey(tag.SiteId)) + ); + } + public async Task InsertAsync(int siteId, string tagName) { var tagNames = await GetTagNamesAsync(siteId); @@ -52,5 +64,203 @@ await _repository.DeleteAsync(Q .CachingRemove(GetCacheKey(siteId)) ); } + + public async Task UpdateAsync(ContentTag tag) + { + await _repository.UpdateAsync(tag, Q + .CachingRemove(GetCacheKey(tag.SiteId)) + ); + } + + public async Task UpdateTagsAsync(List previousTags, List nowTags, int siteId, int contentId) + { + if (ListUtils.Equals(previousTags, nowTags)) return; + + var tagsToRemove = new List(); + var tagsToAdd = new List(); + + if (previousTags != null) + { + foreach (var tag in previousTags) + { + if (!nowTags.Contains(tag)) + { + tagsToRemove.Add(tag); + } + } + } + + if (nowTags != null) + { + foreach (var tag in nowTags) + { + if (previousTags == null || !previousTags.Contains(tag)) + { + tagsToAdd.Add(tag); + } + } + } + + var tags = await GetTagsAsync(siteId); + + foreach (var tagName in tagsToRemove) + { + var tag = ListUtils.FirstOrDefault(tags, x => x.TagName == tagName); + if (tag == null) continue; + + ListUtils.Remove(tag.ContentIds, contentId); + tag.UseNum = ListUtils.Count(tag.ContentIds); + + if (tag.UseNum == 0) + { + await DeleteAsync(siteId, tagName); + } + else + { + await UpdateAsync(tag); + } + } + + foreach (var tagName in tagsToAdd) + { + var tag = ListUtils.FirstOrDefault(tags, x => x.TagName == tagName); + if (tag != null) + { + if (!ListUtils.Contains(tag.ContentIds, contentId)) + { + tag.ContentIds = ListUtils.Add(tag.ContentIds, contentId); + tag.UseNum = tag.ContentIds.Count; + await UpdateAsync(tag); + } + } + else + { + tag = new ContentTag + { + SiteId = siteId, + TagName = tagName, + ContentIds = new List(contentId), + UseNum = 1 + }; + await InsertAsync(tag); + } + } + } + + private string GetCacheKey(int siteId) + { + return CacheUtils.GetListKey(TableName, siteId); + } + + public async Task> GetTagsAsync(int siteId) + { + return await _repository.GetAllAsync(Q + .Where(nameof(ContentTag.SiteId), siteId) + .WhereNotNull(nameof(ContentTag.TagName)) + .WhereNot(nameof(ContentTag.TagName), string.Empty) + .Distinct() + .OrderByDesc(nameof(ContentTag.UseNum)) + .CachingGet(GetCacheKey(siteId)) + ); + } + + public async Task> GetTagNamesAsync(int siteId) + { + var tags = await GetTagsAsync(siteId); + return tags.Select(x => x.TagName).ToList(); + } + + public List GetTagsByLevel(List tagInfoList, int totalNum, int tagLevel) + { + var list = new List(); + var sortedlist = new SortedList(); + foreach (var tagInfo in tagInfoList) + { + list.Add(tagInfo); + + var tagNames = (List)sortedlist[tagInfo.UseNum]; + if (tagNames == null || tagNames.Count == 0) + { + tagNames = new List(); + } + tagNames.Add(tagInfo.TagName); + sortedlist[tagInfo.UseNum] = tagNames; + } + + var count1 = 1; + var count2 = 2; + var count3 = 3; + if (sortedlist.Keys.Count > 3) + { + count1 = (int)Math.Ceiling(0.3 * sortedlist.Keys.Count); + if (count1 < 1) + { + count1 = 1; + } + count2 = (int)Math.Ceiling(0.7 * sortedlist.Keys.Count); + if (count2 == sortedlist.Keys.Count) + { + count2--; + } + if (count2 <= count1) + { + count2++; + } + count3 = count2 + 1; + } + + var currentCount = 0; + foreach (int count in sortedlist.Keys) + { + currentCount++; + + var level = 1; + + if (currentCount <= count1) + { + level = 1; + } + else if (currentCount > count1 && currentCount <= count2) + { + level = 2; + } + else if (currentCount > count2 && currentCount <= count3) + { + level = 3; + } + else if (currentCount > count3) + { + level = 4; + } + + var tagNames = (List)sortedlist[count]; + foreach (var tagInfo in list) + { + if (tagNames.Contains(tagInfo.TagName)) + { + tagInfo.Level = level; + } + } + } + + if (tagLevel > 1) + { + var levelList = new List(); + foreach (var tagInfo in list) + { + if (tagInfo.Level >= tagLevel) + { + levelList.Add(tagInfo); + } + if (totalNum > 0 && levelList.Count > totalNum) + { + break; + } + } + list = levelList; + } + + return list; + } } } \ No newline at end of file diff --git a/src/SSCMS.Core/Repositories/LibraryFileRepository.cs b/src/SSCMS.Core/Repositories/LibraryFileRepository.cs deleted file mode 100644 index 1e6db2fa1..000000000 --- a/src/SSCMS.Core/Repositories/LibraryFileRepository.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Datory; -using SSCMS.Models; -using SSCMS.Repositories; -using SSCMS.Services; - -namespace SSCMS.Core.Repositories -{ - public class LibraryFileRepository : ILibraryFileRepository - { - private readonly Repository _repository; - - public LibraryFileRepository(ISettingsManager settingsManager) - { - _repository = new Repository(settingsManager.Database, settingsManager.Redis); - } - - public IDatabase Database => _repository.Database; - - public string TableName => _repository.TableName; - - public List TableColumns => _repository.TableColumns; - - public async Task InsertAsync(LibraryFile library) - { - return await _repository.InsertAsync(library); - } - - public async Task UpdateAsync(LibraryFile library) - { - return await _repository.UpdateAsync(library); - } - - public async Task DeleteAsync(int libraryId) - { - return await _repository.DeleteAsync(libraryId); - } - - public async Task GetCountAsync(int groupId, string keyword) - { - var query = Q.NewQuery(); - - if (groupId > 0) - { - query.Where(nameof(LibraryFile.GroupId), groupId); - } - - if (!string.IsNullOrEmpty(keyword)) - { - query.Where(q => q - .WhereLike(nameof(LibraryFile.Title), $"%{keyword}%") - .OrWhere(nameof(LibraryFile.FileType), keyword.ToUpper()) - ); - } - - return await _repository.CountAsync(query); - } - - public async Task> GetAllAsync(int groupId, string keyword, int page, int perPage) - { - var query = Q - .OrderByDesc(nameof(LibraryFile.Id)) - .ForPage(page, perPage); - - if (groupId > 0) - { - query.Where(nameof(LibraryFile.GroupId), groupId); - } - if (!string.IsNullOrEmpty(keyword)) - { - query.Where(q => q - .WhereLike(nameof(LibraryFile.Title), $"%{keyword}%") - .OrWhere(nameof(LibraryFile.FileType), keyword.ToUpper()) - ); - } - - return await _repository.GetAllAsync(query); - } - - public async Task GetAsync(int libraryId) - { - return await _repository.GetAsync(libraryId); - } - - public async Task GetUrlByIdAsync(int id) - { - return await _repository.GetAsync(Q - .Select(nameof(LibraryFile.Url)) - .Where(nameof(LibraryFile.Id), id) - ); - } - - public async Task GetUrlByTitleAsync(string title) - { - return await _repository.GetAsync(Q - .Select(nameof(LibraryFile.Url)) - .Where(nameof(LibraryFile.Title), title) - ); - } - } -} diff --git a/src/SSCMS.Core/Repositories/LibraryGroupRepository.cs b/src/SSCMS.Core/Repositories/LibraryGroupRepository.cs deleted file mode 100644 index 1f234f867..000000000 --- a/src/SSCMS.Core/Repositories/LibraryGroupRepository.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Datory; -using SSCMS.Core.Utils; -using SSCMS.Enums; -using SSCMS.Models; -using SSCMS.Repositories; -using SSCMS.Services; - -namespace SSCMS.Core.Repositories -{ - public class LibraryGroupRepository : ILibraryGroupRepository - { - private readonly Repository _repository; - - public LibraryGroupRepository(ISettingsManager settingsManager) - { - _repository = new Repository(settingsManager.Database, settingsManager.Redis); - } - - public IDatabase Database => _repository.Database; - - public string TableName => _repository.TableName; - - public List TableColumns => _repository.TableColumns; - - private string CacheKey(LibraryType type) => CacheUtils.GetListKey(TableName, type.GetValue()); - - public async Task InsertAsync(LibraryGroup group) - { - return await _repository.InsertAsync(group, Q - .CachingRemove(CacheKey(group.LibraryType)) - ); - } - - public async Task UpdateAsync(LibraryGroup group) - { - return await _repository.UpdateAsync(group, Q - .CachingRemove(CacheKey(group.LibraryType)) - ); - } - - public async Task DeleteAsync(LibraryType type, int groupId) - { - return await _repository.DeleteAsync(groupId, Q - .CachingRemove(CacheKey(type)) - ); - } - - public async Task> GetAllAsync(LibraryType type) - { - var list = await _repository.GetAllAsync(Q - .Where(nameof(LibraryGroup.LibraryType), type.GetValue()) - .OrderByDesc(nameof(LibraryGroup.Id)) - .CachingGet(CacheKey(type)) - ); - return list.ToList(); - } - - public async Task GetAsync(int groupId) - { - return await _repository.GetAsync(groupId); - } - - public async Task IsExistsAsync(LibraryType type, string groupName) - { - return await _repository.ExistsAsync(Q - .Where(nameof(LibraryGroup.LibraryType), type.GetValue()) - .Where(nameof(LibraryGroup.GroupName), groupName) - ); - } - } -} diff --git a/src/SSCMS.Core/Repositories/LibraryImageRepository.cs b/src/SSCMS.Core/Repositories/LibraryImageRepository.cs deleted file mode 100644 index e8539cb99..000000000 --- a/src/SSCMS.Core/Repositories/LibraryImageRepository.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Datory; -using SSCMS.Models; -using SSCMS.Repositories; -using SSCMS.Services; - -namespace SSCMS.Core.Repositories -{ - public class LibraryImageRepository : ILibraryImageRepository - { - private readonly Repository _repository; - - public LibraryImageRepository(ISettingsManager settingsManager) - { - _repository = new Repository(settingsManager.Database, settingsManager.Redis); - } - - public IDatabase Database => _repository.Database; - - public string TableName => _repository.TableName; - - public List TableColumns => _repository.TableColumns; - - public async Task InsertAsync(LibraryImage library) - { - return await _repository.InsertAsync(library); - } - - public async Task UpdateAsync(LibraryImage library) - { - return await _repository.UpdateAsync(library); - } - - public async Task DeleteAsync(int libraryId) - { - return await _repository.DeleteAsync(libraryId); - } - - public async Task GetCountAsync(int groupId, string keyword) - { - var query = Q.NewQuery(); - - if (groupId > 0) - { - query.Where(nameof(LibraryImage.GroupId), groupId); - } - - if (!string.IsNullOrEmpty(keyword)) - { - query.WhereLike(nameof(LibraryImage.Title), $"%{keyword}%"); - } - - return await _repository.CountAsync(query); - } - - public async Task> GetAllAsync(int groupId, string keyword, int page, int perPage) - { - var query = Q - .OrderByDesc(nameof(LibraryImage.Id)) - .ForPage(page, perPage); - - if (groupId > 0) - { - query.Where(nameof(LibraryImage.GroupId), groupId); - } - if (!string.IsNullOrEmpty(keyword)) - { - query.WhereLike(nameof(LibraryImage.Title), $"%{keyword}%"); - } - - return await _repository.GetAllAsync(query); - } - - public async Task GetAsync(int libraryId) - { - return await _repository.GetAsync(libraryId); - } - - public async Task GetUrlByIdAsync(int id) - { - return await _repository.GetAsync(Q - .Select(nameof(LibraryImage.Url)) - .Where(nameof(LibraryImage.Id), id) - ); - } - - public async Task GetUrlByTitleAsync(string title) - { - return await _repository.GetAsync(Q - .Select(nameof(LibraryImage.Url)) - .Where(nameof(LibraryImage.Title), title) - ); - } - } -} diff --git a/src/SSCMS.Core/Repositories/LibraryTextRepository.cs b/src/SSCMS.Core/Repositories/LibraryTextRepository.cs deleted file mode 100644 index 758206aea..000000000 --- a/src/SSCMS.Core/Repositories/LibraryTextRepository.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Datory; -using SSCMS.Models; -using SSCMS.Repositories; -using SSCMS.Services; - -namespace SSCMS.Core.Repositories -{ - public class LibraryTextRepository : ILibraryTextRepository - { - private readonly Repository _repository; - - public LibraryTextRepository(ISettingsManager settingsManager) - { - _repository = new Repository(settingsManager.Database, settingsManager.Redis); - } - - public IDatabase Database => _repository.Database; - - public string TableName => _repository.TableName; - - public List TableColumns => _repository.TableColumns; - - public async Task InsertAsync(LibraryText library) - { - return await _repository.InsertAsync(library); - } - - public async Task UpdateAsync(LibraryText library) - { - return await _repository.UpdateAsync(library); - } - - public async Task DeleteAsync(int libraryId) - { - return await _repository.DeleteAsync(libraryId); - } - - public async Task GetCountAsync(int groupId, string keyword) - { - var query = Q.NewQuery(); - - if (groupId > 0) - { - query.Where(nameof(LibraryText.GroupId), groupId); - } - - if (!string.IsNullOrEmpty(keyword)) - { - query.WhereLike(nameof(LibraryText.Title), $"%{keyword}%"); - } - - return await _repository.CountAsync(query); - } - - public async Task> GetAllAsync(int groupId, string keyword, int page, int perPage) - { - var query = Q - .OrderByDesc(nameof(LibraryText.Id)) - .ForPage(page, perPage); - - if (groupId > 0) - { - query.Where(nameof(LibraryText.GroupId), groupId); - } - if (!string.IsNullOrEmpty(keyword)) - { - query.WhereLike(nameof(LibraryText.Title), $"%{keyword}%"); - } - - return await _repository.GetAllAsync(query); - } - - public async Task GetAsync(int libraryId) - { - return await _repository.GetAsync(libraryId); - } - - public async Task GetContentByIdAsync(int id) - { - return await _repository.GetAsync(Q - .Select(nameof(LibraryText.Content)) - .Where(nameof(LibraryText.Id), id) - ); - } - - public async Task GetContentByTitleAsync(string title) - { - return await _repository.GetAsync(Q - .Select(nameof(LibraryText.Content)) - .Where(nameof(LibraryText.Title), title) - ); - } - } -} diff --git a/src/SSCMS.Core/Repositories/LibraryVideoRepository.cs b/src/SSCMS.Core/Repositories/LibraryVideoRepository.cs deleted file mode 100644 index bca00e1fa..000000000 --- a/src/SSCMS.Core/Repositories/LibraryVideoRepository.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Datory; -using SSCMS.Models; -using SSCMS.Repositories; -using SSCMS.Services; - -namespace SSCMS.Core.Repositories -{ - public class LibraryVideoRepository : ILibraryVideoRepository - { - private readonly Repository _repository; - - public LibraryVideoRepository(ISettingsManager settingsManager) - { - _repository = new Repository(settingsManager.Database, settingsManager.Redis); - } - - public IDatabase Database => _repository.Database; - - public string TableName => _repository.TableName; - - public List TableColumns => _repository.TableColumns; - - public async Task InsertAsync(LibraryVideo library) - { - return await _repository.InsertAsync(library); - } - - public async Task UpdateAsync(LibraryVideo library) - { - return await _repository.UpdateAsync(library); - } - - public async Task DeleteAsync(int libraryId) - { - return await _repository.DeleteAsync(libraryId); - } - - public async Task GetCountAsync(int groupId, string keyword) - { - var query = Q.NewQuery(); - - if (groupId > 0) - { - query.Where(nameof(LibraryVideo.GroupId), groupId); - } - - if (!string.IsNullOrEmpty(keyword)) - { - query.WhereLike(nameof(LibraryVideo.Title), $"%{keyword}%"); - } - - return await _repository.CountAsync(query); - } - - public async Task> GetAllAsync(int groupId, string keyword, int page, int perPage) - { - var query = Q - .OrderByDesc(nameof(LibraryVideo.Id)) - .ForPage(page, perPage); - - if (groupId > 0) - { - query.Where(nameof(LibraryVideo.GroupId), groupId); - } - if (!string.IsNullOrEmpty(keyword)) - { - query.WhereLike(nameof(LibraryVideo.Title), $"%{keyword}%"); - } - - return await _repository.GetAllAsync(query); - } - - public async Task GetAsync(int libraryId) - { - return await _repository.GetAsync(libraryId); - } - - public async Task GetUrlByIdAsync(int id) - { - return await _repository.GetAsync(Q - .Select(nameof(LibraryVideo.Url)) - .Where(nameof(LibraryVideo.Id), id) - ); - } - - public async Task GetUrlByTitleAsync(string title) - { - return await _repository.GetAsync(Q - .Select(nameof(LibraryVideo.Url)) - .Where(nameof(LibraryVideo.Title), title) - ); - } - } -} diff --git a/src/SSCMS.Core/Repositories/LogRepository.cs b/src/SSCMS.Core/Repositories/LogRepository.cs index 8d0f36d37..b419d96b6 100644 --- a/src/SSCMS.Core/Repositories/LogRepository.cs +++ b/src/SSCMS.Core/Repositories/LogRepository.cs @@ -1,11 +1,8 @@ using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; -using Dapper; using Datory; using SqlKata; -using SSCMS.Core.Utils; using SSCMS.Models; using SSCMS.Repositories; using SSCMS.Services; @@ -240,147 +237,6 @@ public async Task GetLastRemoveLogDateAsync() return addDate ?? DateTime.MinValue; } - public Dictionary GetAdminLoginDictionaryByDate(DateTime dateFrom, DateTime dateTo, string xType, string actionType) - { - var analysisType = TranslateUtils.ToEnum(xType, AnalysisType.Day); - var dict = new Dictionary(); - - var builder = new StringBuilder(); - if (dateFrom > Constants.SqlMinValue) - { - builder.Append($" AND AddDate >= {SqlUtils.GetComparableDate(Database.DatabaseType, dateFrom)}"); - } - if (dateTo != Constants.SqlMinValue) - { - builder.Append($" AND AddDate < {SqlUtils.GetComparableDate(Database.DatabaseType, dateTo)}"); - } - - string sqlSelectTrackingDay = $@" -SELECT COUNT(*) AS AddNum, AddYear, AddMonth, AddDay FROM ( - SELECT {SqlUtils.GetDatePartYear(Database.DatabaseType, "AddDate")} AS AddYear, {SqlUtils.GetDatePartMonth(Database.DatabaseType, "AddDate")} AS AddMonth, {SqlUtils.GetDatePartDay(Database.DatabaseType, "AddDate")} AS AddDay - FROM siteserver_Log - WHERE {SqlUtils.GetDateDiffLessThanDays(Database.DatabaseType, "AddDate", 30.ToString())} {builder} -) DERIVEDTBL GROUP BY AddYear, AddMonth, AddDay ORDER BY AddNum DESC";//添加日统计 - - if (analysisType == AnalysisType.Month) - { - sqlSelectTrackingDay = $@" -SELECT COUNT(*) AS AddNum, AddYear, AddMonth FROM ( - SELECT {SqlUtils.GetDatePartYear(Database.DatabaseType, "AddDate")} AS AddYear, {SqlUtils.GetDatePartMonth(Database.DatabaseType, "AddDate")} AS AddMonth - FROM siteserver_Log - WHERE {SqlUtils.GetDateDiffLessThanMonths(Database.DatabaseType, "AddDate", 12.ToString())} {builder} -) DERIVEDTBL GROUP BY AddYear, AddMonth ORDER BY AddNum DESC";//添加月统计 - } - else if (analysisType == AnalysisType.Year) - { - sqlSelectTrackingDay = $@" -SELECT COUNT(*) AS AddNum, AddYear FROM ( - SELECT {SqlUtils.GetDatePartYear(Database.DatabaseType, "AddDate")} AS AddYear - FROM siteserver_Log - WHERE {SqlUtils.GetDateDiffLessThanYears(Database.DatabaseType, "AddDate", 10.ToString())} {builder} -) DERIVEDTBL GROUP BY AddYear ORDER BY AddNum DESC -";//添加年统计 - } - - using (var connection = _repository.Database.GetConnection()) - { - using (var rdr = connection.ExecuteReader(sqlSelectTrackingDay)) - { - while (rdr.Read()) - { - var accessNum = rdr.IsDBNull(0) ? 0 : rdr.GetInt32(0); - if (analysisType == AnalysisType.Day) - { - var year = rdr.GetValue(1); - var month = rdr.GetValue(2); - var day = rdr.GetValue(3); - var dateTime = TranslateUtils.ToDateTime($"{year}-{month}-{day}"); - dict.Add(dateTime, accessNum); - } - else if (analysisType == AnalysisType.Month) - { - var year = rdr.GetValue(1); - var month = rdr.GetValue(2); - - var dateTime = TranslateUtils.ToDateTime($"{year}-{month}-1"); - dict.Add(dateTime, accessNum); - } - else if (analysisType == AnalysisType.Year) - { - var year = rdr.GetValue(1); - var dateTime = TranslateUtils.ToDateTime($"{year}-1-1"); - dict.Add(dateTime, accessNum); - } - } - rdr.Close(); - } - } - - - return dict; - } - - public async Task> GetAdminLoginDictionaryByNameAsync(DateTime dateFrom, DateTime dateTo, string actionType) - { - var dict = new Dictionary(); - - var query = Q - .WhereDate(nameof(Log.CreatedDate), ">", DateTime.Now.AddDays(-30)) - .Where(nameof(Log.AdminId), ">", 0); - - if (dateFrom > Constants.SqlMinValue) - { - query.WhereDate(nameof(Log.CreatedDate), ">=", dateFrom); - } - if (dateTo != Constants.SqlMinValue) - { - query.WhereDate(nameof(Log.CreatedDate), "<", dateTo); - } - - var list = await _repository.GetAllAsync<(int adminId, int count)>(query - .SelectRaw("AdminId, COUNT(*)") - .GroupBy(nameof(Log.AdminId)) - ); - - foreach (var (adminId, count) in list) - { - var admin = await _administratorRepository.GetByUserIdAsync(adminId); - if (admin != null) - { - dict[admin.UserName] = count; - } - } - -// string sqlSelectTrackingDay = $@" -//SELECT COUNT(*) AS AddNum, UserName FROM ( -// SELECT {SqlUtils.GetDatePartYear("AddDate")} AS AddYear, {SqlUtils.GetDatePartMonth("AddDate")} AS AddMonth, {SqlUtils.GetDatePartDay("AddDate")} AS AddDay, UserName -// FROM siteserver_Log -// WHERE {SqlUtils.GetDateDiffLessThanDays("AddDate", 30.ToString())} -// {builder} -//) DERIVEDTBL GROUP BY UserName ORDER BY AddNum DESC";//添加日统计 - - -// using (var connection = _repository.Database.GetConnection()) -// { -// using (var rdr = connection.ExecuteReader(sqlSelectTrackingDay)) -// { -// while (rdr.Read()) -// { -// var accessNum = rdr.IsDBNull(0) ? 0 : rdr.GetInt32(0); -// var userName = rdr.IsDBNull(1) ? string.Empty : rdr.GetString(1); -// if (!string.IsNullOrEmpty(userName)) -// { -// dict[userName] = accessNum; -// } - -// } -// rdr.Close(); -// } -// } - - return dict; - } - public async Task> GetUserLogsAsync(int userId, int offset, int limit) { return await _repository.GetAllAsync(Q diff --git a/src/SSCMS.Core/Repositories/MaterialArticleRepository.cs b/src/SSCMS.Core/Repositories/MaterialArticleRepository.cs new file mode 100644 index 000000000..fa7036d9f --- /dev/null +++ b/src/SSCMS.Core/Repositories/MaterialArticleRepository.cs @@ -0,0 +1,141 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Core.Repositories +{ + public class MaterialArticleRepository : IMaterialArticleRepository + { + private readonly ISettingsManager _settingsManager; + private readonly Repository _repository; + + public MaterialArticleRepository(ISettingsManager settingsManager) + { + _settingsManager = settingsManager; + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + CacheKey = CacheUtils.GetListKey(_repository.TableName); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string CacheKey { get; } + + public async Task InsertAsync(MaterialArticle article) + { + return await _repository.InsertAsync(article, Q + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateAsync(MaterialArticle article) + { + return await _repository.UpdateAsync(article, Q + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateUrlAsync(int id, string url) + { + await _repository.UpdateAsync(Q + .Set(nameof(MaterialArticle.Url), url) + .Where(nameof(MaterialArticle.Id), id) + .CachingRemove(CacheKey) + ); + } + + public async Task DeleteAsync(int id) + { + var article = await GetAsync(id); + if (article != null && !string.IsNullOrEmpty(article.ThumbUrl)) + { + var filePath = PathUtils.Combine(_settingsManager.WebRootPath, article.ThumbUrl); + FileUtils.DeleteFileIfExists(filePath); + } + + return await _repository.DeleteAsync(id, Q + .CachingRemove(CacheKey) + ); + } + + public async Task GetCountAsync(int groupId, string keyword, List articleIds = null) + { + var articles = await GetAllAsync(); + + if (articleIds != null && articleIds.Count > 0) + { + articles = articles.Where(x => !articleIds.Contains(x.Id)).ToList(); + } + + if (groupId != 0) + { + articles = articles.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + articles = articles.Where(x => StringUtils.ContainsIgnoreCase(x.Title, keyword)).ToList(); + } + + return articles.Count; + } + + private async Task> GetAllAsync() + { + return await _repository.GetAllAsync(Q + .OrderByDesc(nameof(MaterialArticle.Id)) + .CachingGet(CacheKey) + ); + } + + public async Task> GetAllAsync(int groupId, string keyword, int page, int perPage, List articleIds = null) + { + var articles = await GetAllAsync(); + + if (articleIds != null && articleIds.Count > 0) + { + articles = articles.Where(x => !articleIds.Contains(x.Id)).ToList(); + } + + if (groupId != 0) + { + articles = articles.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + articles = articles.Where(x => StringUtils.ContainsIgnoreCase(x.Title, keyword)).ToList(); + } + + return articles.Skip((page - 1) * perPage).Take(perPage).ToList(); + } + + public async Task GetAsync(int id) + { + var articles = await GetAllAsync(); + return articles.FirstOrDefault(x => x.Id == id); + } + + public async Task GetBodyByIdAsync(int id) + { + var article = await GetAsync(id); + return article?.Content; + } + + public async Task GetBodyByTitleAsync(string title) + { + var articles = await GetAllAsync(); + var article = articles.FirstOrDefault(x => x.Title == title); + return article?.Content; + } + } +} diff --git a/src/SSCMS.Core/Repositories/MaterialAudioRepository.cs b/src/SSCMS.Core/Repositories/MaterialAudioRepository.cs new file mode 100644 index 000000000..e75e778f7 --- /dev/null +++ b/src/SSCMS.Core/Repositories/MaterialAudioRepository.cs @@ -0,0 +1,139 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Core.Repositories +{ + public class MaterialAudioRepository : IMaterialAudioRepository + { + private readonly ISettingsManager _settingsManager; + private readonly Repository _repository; + + public MaterialAudioRepository(ISettingsManager settingsManager) + { + _settingsManager = settingsManager; + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + CacheKey = CacheUtils.GetListKey(_repository.TableName); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string CacheKey { get; } + + public async Task InsertAsync(MaterialAudio audio) + { + return await _repository.InsertAsync(audio, Q + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateAsync(MaterialAudio audio) + { + return await _repository.UpdateAsync(audio, Q + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateMediaIdAsync(int id, string mediaId) + { + await _repository.UpdateAsync(Q + .Set(nameof(MaterialAudio.MediaId), mediaId) + .Where(nameof(MaterialAudio.Id), id) + .CachingRemove(CacheKey) + ); + } + + public async Task DeleteAsync(int id) + { + var audio = await GetAsync(id); + if (audio != null && !string.IsNullOrEmpty(audio.Url)) + { + var filePath = PathUtils.Combine(_settingsManager.WebRootPath, audio.Url); + FileUtils.DeleteFileIfExists(filePath); + } + + return await _repository.DeleteAsync(id, Q + .CachingRemove(CacheKey) + ); + } + + public async Task GetCountAsync(int groupId, string keyword) + { + var audios = await GetAllAsync(); + + if (groupId != 0) + { + audios = audios.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + audios = audios.Where(x => StringUtils.ContainsIgnoreCase(x.Title, keyword)).ToList(); + } + + return audios.Count; + } + + private async Task> GetAllAsync() + { + return await _repository.GetAllAsync(Q + .OrderByDesc(nameof(MaterialAudio.Id)) + .CachingGet(CacheKey) + ); + } + + public async Task> GetAllAsync(int groupId, string keyword, int page, int perPage) + { + var audios = await GetAllAsync(); + + if (groupId != 0) + { + audios = audios.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + audios = audios.Where(x => StringUtils.ContainsIgnoreCase(x.Title, keyword)).ToList(); + } + + return audios.Skip((page - 1) * perPage).Take(perPage).ToList(); + } + + public async Task GetAsync(int id) + { + var audios = await GetAllAsync(); + return audios.FirstOrDefault(x => x.Id == id); + } + + public async Task GetUrlByIdAsync(int id) + { + var audio = await GetAsync(id); + return audio?.Url; + } + + public async Task GetUrlByTitleAsync(string title) + { + var audios = await GetAllAsync(); + var audio = audios.FirstOrDefault(x => x.Title == title); + return audio?.Url; + } + + public async Task IsExistsAsync(string mediaId) + { + if (string.IsNullOrEmpty(mediaId)) return false; + + var audios = await GetAllAsync(); + return audios.Exists(x => x.MediaId == mediaId); + } + } +} diff --git a/src/SSCMS.Core/Repositories/MaterialFileRepository.cs b/src/SSCMS.Core/Repositories/MaterialFileRepository.cs new file mode 100644 index 000000000..42165d6b4 --- /dev/null +++ b/src/SSCMS.Core/Repositories/MaterialFileRepository.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Core.Repositories +{ + public class MaterialFileRepository : IMaterialFileRepository + { + private readonly ISettingsManager _settingsManager; + private readonly Repository _repository; + + public MaterialFileRepository(ISettingsManager settingsManager) + { + _settingsManager = settingsManager; + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + CacheKey = CacheUtils.GetListKey(_repository.TableName); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string CacheKey { get; } + + public async Task InsertAsync(MaterialFile file) + { + return await _repository.InsertAsync(file, Q + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateAsync(MaterialFile file) + { + return await _repository.UpdateAsync(file, Q + .CachingRemove(CacheKey) + ); + } + + public async Task DeleteAsync(int id) + { + var file = await GetAsync(id); + if (file != null && !string.IsNullOrEmpty(file.Url)) + { + var filePath = PathUtils.Combine(_settingsManager.WebRootPath, file.Url); + FileUtils.DeleteFileIfExists(filePath); + } + + return await _repository.DeleteAsync(id, Q + .CachingRemove(CacheKey) + ); + } + + public async Task GetCountAsync(int groupId, string keyword) + { + var files = await GetAllAsync(); + + if (groupId != 0) + { + files = files.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + files = files.Where(x => StringUtils.ContainsIgnoreCase(x.Title, keyword)).ToList(); + } + + return files.Count; + } + + private async Task> GetAllAsync() + { + return await _repository.GetAllAsync(Q + .OrderByDesc(nameof(MaterialFile.Id)) + .CachingGet(CacheKey) + ); + } + + public async Task> GetAllAsync(int groupId, string keyword, int page, int perPage) + { + var files = await GetAllAsync(); + + if (groupId != 0) + { + files = files.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + files = files.Where(x => StringUtils.ContainsIgnoreCase(x.Title, keyword)).ToList(); + } + + return files.Skip((page - 1) * perPage).Take(perPage).ToList(); + } + + public async Task GetAsync(int id) + { + var files = await GetAllAsync(); + return files.FirstOrDefault(x => x.Id == id); + } + + public async Task GetUrlByIdAsync(int id) + { + var file = await GetAsync(id); + return file?.Url; + } + + public async Task GetUrlByTitleAsync(string title) + { + var files = await GetAllAsync(); + var file = files.FirstOrDefault(x => x.Title == title); + return file?.Url; + } + + public async Task IsExistsAsync(string mediaId) + { + if (string.IsNullOrEmpty(mediaId)) return false; + + var files = await GetAllAsync(); + return files.Exists(x => x.MediaId == mediaId); + } + } +} diff --git a/src/SSCMS.Core/Repositories/MaterialGroupRepository.cs b/src/SSCMS.Core/Repositories/MaterialGroupRepository.cs new file mode 100644 index 000000000..505201f1a --- /dev/null +++ b/src/SSCMS.Core/Repositories/MaterialGroupRepository.cs @@ -0,0 +1,95 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Enums; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Core.Repositories +{ + public class MaterialGroupRepository : IMaterialGroupRepository + { + private readonly Repository _repository; + private readonly ISiteRepository _siteRepository; + + public MaterialGroupRepository(ISettingsManager settingsManager, ISiteRepository siteRepository) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + _siteRepository = siteRepository; + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string CacheKey(MaterialType type) => CacheUtils.GetListKey(TableName, type.GetValue()); + + public async Task InsertAsync(MaterialGroup group) + { + return await _repository.InsertAsync(group, Q + .CachingRemove(CacheKey(group.LibraryType)) + ); + } + + public async Task UpdateAsync(MaterialGroup group) + { + return await _repository.UpdateAsync(group, Q + .CachingRemove(CacheKey(group.LibraryType)) + ); + } + + public async Task DeleteAsync(MaterialType type, int groupId) + { + return await _repository.DeleteAsync(groupId, Q + .CachingRemove(CacheKey(type)) + ); + } + + public async Task> GetAllAsync(MaterialType type) + { + var groups = new List + { + new MaterialGroup + { + Id = 0, + LibraryType = type, + GroupName = "全部" + } + }; + + var sites = await _siteRepository.GetSitesAsync(); + groups.AddRange(sites.Select(site => new MaterialGroup + { + Id = -site.Id, + LibraryType = type, + GroupName = site.SiteName + })); + + var list = await _repository.GetAllAsync(Q + .Where(nameof(MaterialGroup.LibraryType), type.GetValue()) + .OrderBy(nameof(MaterialGroup.Id)) + .CachingGet(CacheKey(type)) + ); + + groups.AddRange(list); + return groups; + } + + public async Task GetAsync(int groupId) + { + return await _repository.GetAsync(groupId); + } + + public async Task IsExistsAsync(MaterialType type, string groupName) + { + var groups = await GetAllAsync(type); + return groups.Exists(x => StringUtils.EqualsIgnoreCase(groupName, x.GroupName)); + } + } +} diff --git a/src/SSCMS.Core/Repositories/MaterialImageRepository.cs b/src/SSCMS.Core/Repositories/MaterialImageRepository.cs new file mode 100644 index 000000000..b29873f84 --- /dev/null +++ b/src/SSCMS.Core/Repositories/MaterialImageRepository.cs @@ -0,0 +1,139 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Core.Repositories +{ + public class MaterialImageRepository : IMaterialImageRepository + { + private readonly ISettingsManager _settingsManager; + private readonly Repository _repository; + + public MaterialImageRepository(ISettingsManager settingsManager) + { + _settingsManager = settingsManager; + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + CacheKey = CacheUtils.GetListKey(_repository.TableName); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string CacheKey { get; } + + public async Task InsertAsync(MaterialImage image) + { + return await _repository.InsertAsync(image, Q + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateAsync(MaterialImage image) + { + return await _repository.UpdateAsync(image, Q + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateMediaIdAsync(int id, string mediaId) + { + await _repository.UpdateAsync(Q + .Set(nameof(MaterialImage.MediaId), mediaId) + .Where(nameof(MaterialImage.Id), id) + .CachingRemove(CacheKey) + ); + } + + public async Task DeleteAsync(int id) + { + var image = await GetAsync(id); + if (image != null && !string.IsNullOrEmpty(image.Url)) + { + var filePath = PathUtils.Combine(_settingsManager.WebRootPath, image.Url); + FileUtils.DeleteFileIfExists(filePath); + } + + return await _repository.DeleteAsync(id, Q + .CachingRemove(CacheKey) + ); + } + + public async Task GetCountAsync(int groupId, string keyword) + { + var images = await GetAllAsync(); + + if (groupId != 0) + { + images = images.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + images = images.Where(x => StringUtils.ContainsIgnoreCase(x.Title, keyword)).ToList(); + } + + return images.Count; + } + + private async Task> GetAllAsync() + { + return await _repository.GetAllAsync(Q + .OrderByDesc(nameof(MaterialImage.Id)) + .CachingGet(CacheKey) + ); + } + + public async Task> GetAllAsync(int groupId, string keyword, int page, int perPage) + { + var images = await GetAllAsync(); + + if (groupId != 0) + { + images = images.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + images = images.Where(x => StringUtils.ContainsIgnoreCase(x.Title, keyword)).ToList(); + } + + return images.Skip((page - 1) * perPage).Take(perPage).ToList(); + } + + public async Task GetAsync(int id) + { + var images = await GetAllAsync(); + return images.FirstOrDefault(x => x.Id == id); + } + + public async Task GetUrlByIdAsync(int id) + { + var image = await GetAsync(id); + return image?.Url; + } + + public async Task GetUrlByTitleAsync(string title) + { + var images = await GetAllAsync(); + var image = images.FirstOrDefault(x => x.Title == title); + return image?.Url; + } + + public async Task IsExistsAsync(string mediaId) + { + if (string.IsNullOrEmpty(mediaId)) return false; + + var images = await GetAllAsync(); + return images.Exists(x => x.MediaId == mediaId); + } + } +} diff --git a/src/SSCMS.Core/Repositories/MaterialMessageItemRepository.cs b/src/SSCMS.Core/Repositories/MaterialMessageItemRepository.cs new file mode 100644 index 000000000..fd60303bd --- /dev/null +++ b/src/SSCMS.Core/Repositories/MaterialMessageItemRepository.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Enums; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; + +namespace SSCMS.Core.Repositories +{ + public class MaterialMessageItemRepository : IMaterialMessageItemRepository + { + private readonly Repository _repository; + private readonly IMaterialArticleRepository _materialArticleRepository; + private readonly IMaterialImageRepository _materialImageRepository; + private readonly IMaterialVideoRepository _materialVideoRepository; + private readonly IMaterialAudioRepository _materialAudioRepository; + private readonly IMaterialFileRepository _materialFileRepository; + + public MaterialMessageItemRepository(ISettingsManager settingsManager, IMaterialArticleRepository materialArticleRepository, IMaterialImageRepository materialImageRepository, IMaterialVideoRepository materialVideoRepository, IMaterialAudioRepository materialAudioRepository, IMaterialFileRepository materialFileRepository) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + _materialArticleRepository = materialArticleRepository; + _materialImageRepository = materialImageRepository; + _materialVideoRepository = materialVideoRepository; + _materialAudioRepository = materialAudioRepository; + _materialFileRepository = materialFileRepository; + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string GetCacheKey(int messageId) + { + return CacheUtils.GetListKey(_repository.TableName, messageId); + } + + public async Task InsertAsync(MaterialMessageItem item) + { + return await _repository.InsertAsync(item, Q + .CachingRemove(GetCacheKey(item.MessageId)) + ); + } + + public async Task DeleteAllAsync(int messageId) + { + await _repository.DeleteAsync(Q + .Where(nameof(MaterialMessageItem.MessageId), messageId) + .CachingRemove(GetCacheKey(messageId)) + ); + } + + public async Task> GetAllAsync(int messageId) + { + var items = await _repository.GetAllAsync(Q + .Where(nameof(MaterialMessageItem.MessageId), messageId) + .OrderBy(nameof(MaterialMessageItem.Taxis)) + .CachingGet(GetCacheKey(messageId)) + ); + + foreach (var item in items) + { + if (item.MaterialType == MaterialType.Article) + { + var article = await _materialArticleRepository.GetAsync(item.MaterialId); + + item.ThumbMediaId = article.ThumbMediaId; + item.Author = article.Author; + item.Title = article.Title; + item.ContentSourceUrl = article.ContentSourceUrl; + item.Content = article.Content; + item.Digest = article.Digest; + item.ShowCoverPic = article.ShowCoverPic; + item.ThumbUrl = article.ThumbUrl; + item.CommentType = article.CommentType; + } + //else if (item.MaterialType == MaterialType.Image) + //{ + // var image = await _materialImageRepository.GetAsync(item.MaterialId); + // item.Title = image.Title; + // item.ImageUrl = image.Url; + //} + //else if (item.MaterialType == MaterialType.Video) + //{ + // var video = await _materialVideoRepository.GetAsync(item.MaterialId); + // item.Title = video.Title; + //} + //else if (item.MaterialType == MaterialType.Audio) + //{ + // var audio = await _materialAudioRepository.GetAsync(item.MaterialId); + // item.Title = audio.Title; + //} + //else if (item.MaterialType == MaterialType.File) + //{ + // var file = await _materialFileRepository.GetAsync(item.MaterialId); + // item.Title = file.Title; + //} + } + + return items; + } + + public async Task IsDeletable(MaterialType materialType, int materialId) + { + var count = await _repository.CountAsync(Q + .Where(nameof(MaterialMessageItem.MaterialType), materialType.GetValue()) + .Where(nameof(MaterialMessageItem.MaterialId), materialId) + ); + return count <= 1; + } + } +} diff --git a/src/SSCMS.Core/Repositories/MaterialMessageRepository.cs b/src/SSCMS.Core/Repositories/MaterialMessageRepository.cs new file mode 100644 index 000000000..9fa9f4194 --- /dev/null +++ b/src/SSCMS.Core/Repositories/MaterialMessageRepository.cs @@ -0,0 +1,307 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Enums; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Core.Repositories +{ + public class MaterialMessageRepository : IMaterialMessageRepository + { + private readonly Repository _repository; + private readonly IMaterialArticleRepository _materialArticleRepository; + private readonly IMaterialMessageItemRepository _materialMessageItemRepository; + + public MaterialMessageRepository(ISettingsManager settingsManager, IMaterialArticleRepository materialArticleRepository, IMaterialMessageItemRepository materialMessageItemRepository) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + CacheKey = CacheUtils.GetListKey(_repository.TableName); + _materialArticleRepository = materialArticleRepository; + _materialMessageItemRepository = materialMessageItemRepository; + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string CacheKey { get; } + + public async Task InsertAsync(int groupId, string title, string imageUrl, string summary, string body) + { + var article = new MaterialArticle + { + GroupId = groupId, + ThumbMediaId = string.Empty, + Author = string.Empty, + Title = title, + ContentSourceUrl = string.Empty, + Content = body, + Digest = summary, + ShowCoverPic = !string.IsNullOrEmpty(imageUrl), + ThumbUrl = imageUrl, + CommentType = CommentType.Block + }; + + var materialId = await _materialArticleRepository.InsertAsync(article); + + var messageId = await _repository.InsertAsync( + new MaterialMessage + { + GroupId = groupId + }, + Q.CachingRemove(CacheKey) + ); + + var item = new MaterialMessageItem + { + MessageId = messageId, + MaterialType = MaterialType.Article, + MaterialId = materialId, + Taxis = 1 + }; + await _materialMessageItemRepository.InsertAsync(item); + } + + public async Task InsertAsync(int groupId, string mediaId, List items) + { + var messageId = await _repository.InsertAsync( + new MaterialMessage + { + GroupId = groupId, + MediaId = mediaId + }, + Q.CachingRemove(CacheKey) + ); + + var taxis = 1; + foreach (var item in items) + { + var materialId = item.MaterialId; + if (materialId > 0) + { + var article = await _materialArticleRepository.GetAsync(materialId); + + article.ThumbMediaId = item.ThumbMediaId; + article.Author = item.Author; + article.Title = item.Title; + article.ContentSourceUrl = item.ContentSourceUrl; + article.Content = item.Content; + article.Digest = item.Digest; + article.ShowCoverPic = item.ShowCoverPic; + article.ThumbUrl = item.ThumbUrl; + article.CommentType = item.CommentType; + + await _materialArticleRepository.UpdateAsync(article); + } + else + { + materialId = await _materialArticleRepository.InsertAsync(new MaterialArticle + { + GroupId = groupId, + ThumbMediaId = item.ThumbMediaId, + Author = item.Author, + Title = item.Title, + ContentSourceUrl = item.ContentSourceUrl, + Content = item.Content, + Digest = item.Digest, + ShowCoverPic = item.ShowCoverPic, + ThumbUrl = item.ThumbUrl, + CommentType = item.CommentType + }); + } + + await _materialMessageItemRepository.InsertAsync(new MaterialMessageItem + { + MessageId = messageId, + MaterialType = MaterialType.Article, + MaterialId = materialId, + Taxis = taxis++ + }); + } + + await _repository.RemoveCacheAsync(CacheKey); + + return messageId; + } + + public async Task UpdateAsync(int id, int groupId, List items) + { + await _materialMessageItemRepository.DeleteAllAsync(id); + + var taxis = 1; + foreach (var item in items) + { + var materialId = item.MaterialId; + if (materialId > 0) + { + var article = await _materialArticleRepository.GetAsync(materialId); + + article.ThumbMediaId = item.ThumbMediaId; + article.Author = item.Author; + article.Title = item.Title; + article.ContentSourceUrl = item.ContentSourceUrl; + article.Content = item.Content; + article.Digest = item.Digest; + article.ShowCoverPic = item.ShowCoverPic; + article.ThumbUrl = item.ThumbUrl; + article.CommentType = item.CommentType; + await _materialArticleRepository.UpdateAsync(article); + } + else + { + materialId = await _materialArticleRepository.InsertAsync(new MaterialArticle + { + GroupId = groupId, + ThumbMediaId = item.ThumbMediaId, + Author = item.Author, + Title = item.Title, + ContentSourceUrl = item.ContentSourceUrl, + Content = item.Content, + Digest = item.Digest, + ShowCoverPic = item.ShowCoverPic, + ThumbUrl = item.ThumbUrl, + CommentType = item.CommentType + }); + } + + await _materialMessageItemRepository.InsertAsync(new MaterialMessageItem + { + MessageId = id, + MaterialType = MaterialType.Article, + MaterialId = materialId, + Taxis = taxis++ + }); + } + + await _repository.UpdateAsync(Q + .Set(nameof(MaterialMessage.GroupId), groupId) + .Where(nameof(MaterialMessage.Id), id) + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateAsync(int id, int groupId) + { + await _repository.UpdateAsync(Q + .Set(nameof(MaterialMessage.GroupId), groupId) + .Where(nameof(MaterialMessage.Id), id) + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateMediaIdAsync(int id, string mediaId) + { + await _repository.UpdateAsync(Q + .Set(nameof(MaterialMessage.MediaId), mediaId) + .Where(nameof(MaterialMessage.Id), id) + .CachingRemove(CacheKey) + ); + } + + public async Task DeleteAsync(int id) + { + var message = await GetAsync(id); + foreach (var item in message.Items) + { + if (!await _materialMessageItemRepository.IsDeletable(item.MaterialType, item.MaterialId)) continue; + + if (item.MaterialType == MaterialType.Article) + { + await _materialArticleRepository.DeleteAsync(item.MaterialId); + } + } + + await _materialMessageItemRepository.DeleteAllAsync(message.Id); + + return await _repository.DeleteAsync(id, Q + .CachingRemove(CacheKey) + ); + } + + public async Task GetCountAsync(int groupId, string keyword) + { + var messages = await GetAllAsync(); + + if (groupId != 0) + { + messages = messages.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + messages = messages.Where(x => + { + return x.Items.Exists(item => + StringUtils.ContainsIgnoreCase(item.Title, keyword) || + StringUtils.ContainsIgnoreCase(item.Digest, keyword) || + StringUtils.ContainsIgnoreCase(item.Content, keyword)); + }).ToList(); + } + + return messages.Count; + } + + private async Task> GetAllAsync() + { + var messages = await _repository.GetAllAsync(Q + .OrderByDesc(nameof(MaterialArticle.LastModifiedDate)) + .CachingGet(CacheKey) + ); + + var itemMessages = new List(); + foreach (var message in messages) + { + message.Items = await _materialMessageItemRepository.GetAllAsync(message.Id); + if (message.Items == null || message.Items.Count == 0) continue; + itemMessages.Add(message); + } + + return itemMessages; + } + + public async Task> GetAllAsync(int groupId, string keyword, int page, int perPage) + { + var messages = await GetAllAsync(); + + if (groupId != 0) + { + messages = messages.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + messages = messages.Where(x => + { + return x.Items.Exists(item => + StringUtils.ContainsIgnoreCase(item.Title, keyword) || + StringUtils.ContainsIgnoreCase(item.Digest, keyword) || + StringUtils.ContainsIgnoreCase(item.Content, keyword)); + }).ToList(); + } + + return messages.Skip((page - 1) * perPage).Take(perPage).ToList(); + } + + public async Task GetAsync(int id) + { + if (id == 0) return null; + var messages = await GetAllAsync(); + return messages.FirstOrDefault(x => x.Id == id); + } + + public async Task IsExistsAsync(string mediaId) + { + if (string.IsNullOrEmpty(mediaId)) return false; + + var messages = await GetAllAsync(); + return messages.Exists(x => x.MediaId == mediaId); + } + } +} diff --git a/src/SSCMS.Core/Repositories/MaterialVideoRepository.cs b/src/SSCMS.Core/Repositories/MaterialVideoRepository.cs new file mode 100644 index 000000000..57605952c --- /dev/null +++ b/src/SSCMS.Core/Repositories/MaterialVideoRepository.cs @@ -0,0 +1,139 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Core.Repositories +{ + public class MaterialVideoRepository : IMaterialVideoRepository + { + private readonly ISettingsManager _settingsManager; + private readonly Repository _repository; + + public MaterialVideoRepository(ISettingsManager settingsManager) + { + _settingsManager = settingsManager; + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + CacheKey = CacheUtils.GetListKey(_repository.TableName); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string CacheKey { get; } + + public async Task InsertAsync(MaterialVideo video) + { + return await _repository.InsertAsync(video, Q + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateAsync(MaterialVideo video) + { + return await _repository.UpdateAsync(video, Q + .CachingRemove(CacheKey) + ); + } + + public async Task UpdateMediaIdAsync(int id, string mediaId) + { + await _repository.UpdateAsync(Q + .Set(nameof(MaterialVideo.MediaId), mediaId) + .Where(nameof(MaterialVideo.Id), id) + .CachingRemove(CacheKey) + ); + } + + public async Task DeleteAsync(int id) + { + var video = await GetAsync(id); + if (video != null && !string.IsNullOrEmpty(video.Url)) + { + var filePath = PathUtils.Combine(_settingsManager.WebRootPath, video.Url); + FileUtils.DeleteFileIfExists(filePath); + } + + return await _repository.DeleteAsync(id, Q + .CachingRemove(CacheKey) + ); + } + + public async Task GetCountAsync(int groupId, string keyword) + { + var videos = await GetAllAsync(); + + if (groupId != 0) + { + videos = videos.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + videos = videos.Where(x => StringUtils.ContainsIgnoreCase(x.Title, keyword)).ToList(); + } + + return videos.Count; + } + + private async Task> GetAllAsync() + { + return await _repository.GetAllAsync(Q + .OrderByDesc(nameof(MaterialVideo.Id)) + .CachingGet(CacheKey) + ); + } + + public async Task> GetAllAsync(int groupId, string keyword, int page, int perPage) + { + var videos = await GetAllAsync(); + + if (groupId != 0) + { + videos = videos.Where(x => x.GroupId == groupId).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + videos = videos.Where(x => StringUtils.ContainsIgnoreCase(x.Title, keyword)).ToList(); + } + + return videos.Skip((page - 1) * perPage).Take(perPage).ToList(); + } + + public async Task GetAsync(int id) + { + var videos = await GetAllAsync(); + return videos.FirstOrDefault(x => x.Id == id); + } + + public async Task GetUrlByIdAsync(int id) + { + var video = await GetAsync(id); + return video?.Url; + } + + public async Task GetUrlByTitleAsync(string title) + { + var videos = await GetAllAsync(); + var video = videos.FirstOrDefault(x => x.Title == title); + return video?.Url; + } + + public async Task IsExistsAsync(string mediaId) + { + if (string.IsNullOrEmpty(mediaId)) return false; + + var videos = await GetAllAsync(); + return videos.Exists(x => x.MediaId == mediaId); + } + } +} diff --git a/src/SSCMS.Core/Repositories/SiteRepository.Cache.cs b/src/SSCMS.Core/Repositories/SiteRepository.Cache.cs index a123a62c6..2af0bbf8f 100644 --- a/src/SSCMS.Core/Repositories/SiteRepository.Cache.cs +++ b/src/SSCMS.Core/Repositories/SiteRepository.Cache.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using SSCMS.Dto; using SSCMS.Models; -using SSCMS.Services; using SSCMS.Utils; namespace SSCMS.Core.Repositories @@ -216,17 +215,17 @@ public async Task> GetSiteIdsAsync(int parentId) return siteIdList; } - public async Task> GetSiteTableNamesAsync(IOldPluginManager pluginManager) + public async Task> GetSiteTableNamesAsync() { - return await GetTableNamesAsync(pluginManager, true, false); + return await GetTableNamesAsync(true, false); } - public async Task> GetAllTableNamesAsync(IOldPluginManager pluginManager) + public async Task> GetAllTableNamesAsync() { - return await GetTableNamesAsync(pluginManager, true, true); + return await GetTableNamesAsync(true, true); } - private async Task> GetTableNamesAsync(IOldPluginManager pluginManager, bool includeSiteTables, bool includePluginTables) + private async Task> GetTableNamesAsync(bool includeSiteTables, bool includePluginTables) { var tableNames = new List(); @@ -244,7 +243,7 @@ private async Task> GetTableNamesAsync(IOldPluginManager pluginMana if (includePluginTables) { - var pluginTableNames = pluginManager.GetContentTableNameList(); + var pluginTableNames = _settingsManager.GetContentTableNames(); foreach (var pluginTableName in pluginTableNames) { if (!string.IsNullOrEmpty(pluginTableName) && !ListUtils.ContainsIgnoreCase(tableNames, pluginTableName)) @@ -257,18 +256,18 @@ private async Task> GetTableNamesAsync(IOldPluginManager pluginMana return tableNames; } - public async Task> GetTableNamesAsync(IOldPluginManager pluginManager, Site site) + public async Task> GetTableNamesAsync(Site site) { var tableNames = new List { site.TableName }; var channelSummaries = await _channelRepository.GetSummariesAsync(site.Id); + var pluginTableNames = _settingsManager.GetContentTableNames(); foreach (var summary in channelSummaries) { - if (!string.IsNullOrEmpty(summary.ContentModelPluginId)) + if (!string.IsNullOrEmpty(summary.TableName)) { - var plugin = pluginManager.GetPlugin(summary.ContentModelPluginId); - if (plugin != null && !string.IsNullOrEmpty(plugin.ContentTableName) && !tableNames.Contains(plugin.ContentTableName)) + if (ListUtils.Contains(pluginTableNames, summary.TableName)) { - tableNames.Add(plugin.ContentTableName); + tableNames.Add(summary.TableName); } } } @@ -372,6 +371,30 @@ public async Task> GetSitesWithChildrenAsync(int parentId, Func> GetCascadeAsync(SiteSummary summary, Func func = null) + { + object extra = null; + if (func != null) + { + extra = func(summary); + } + var cascade = new Cascade + { + Value = summary.Id, + Label = summary.SiteName, + Children = await GetCascadeChildrenAsync(summary.Id, func) + }; + if (extra == null) return cascade; + + var dict = TranslateUtils.ToDictionary(extra); + foreach (var o in dict) + { + cascade[o.Key] = o.Value; + } + + return cascade; + } + private async Task> GetCascadeAsync(SiteSummary summary, Func> func = null) { object extra = null; @@ -396,6 +419,25 @@ private async Task> GetCascadeAsync(SiteSummary summary, Func>> GetCascadeChildrenAsync(int parentId, + Func func) + { + var list = new List>(); + + var summaries = await GetSummariesAsync(parentId); + foreach (var summary in summaries) + { + if (summary == null || summary.Id == 0) continue; + var site = await GetCascadeAsync(summary, func); + if (site != null) + { + list.Add(site); + } + } + + return list; + } + public async Task>> GetCascadeChildrenAsync(int parentId, Func> func = null) { var list = new List>(); diff --git a/src/SSCMS.Core/Repositories/SiteRepository.Select.cs b/src/SSCMS.Core/Repositories/SiteRepository.Select.cs index 524e5ccb3..bcfc80731 100644 --- a/src/SSCMS.Core/Repositories/SiteRepository.Select.cs +++ b/src/SSCMS.Core/Repositories/SiteRepository.Select.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Datory; +using SSCMS.Configuration; using SSCMS.Core.Utils; using SSCMS.Models; @@ -26,12 +27,9 @@ public async Task GetAsync(int siteId) var site = await _repository.GetAsync(siteId, Q .CachingGet(GetEntityKey(siteId)) ); - if (site != null) + if (site != null && string.IsNullOrEmpty(site.SiteType)) { - if (string.IsNullOrEmpty(site.SiteType)) - { - site.SiteType = AuthTypes.Resources.Site; - } + site.SiteType = Types.SiteTypes.Web; } return site; diff --git a/src/SSCMS.Core/Repositories/SiteRepository.cs b/src/SSCMS.Core/Repositories/SiteRepository.cs index 3abd6f60c..3df9c6a3b 100644 --- a/src/SSCMS.Core/Repositories/SiteRepository.cs +++ b/src/SSCMS.Core/Repositories/SiteRepository.cs @@ -13,22 +13,18 @@ namespace SSCMS.Core.Repositories public partial class SiteRepository : ISiteRepository { private readonly Repository _repository; + private readonly ISettingsManager _settingsManager; private readonly IChannelRepository _channelRepository; private readonly IAdministratorRepository _administratorRepository; private readonly ITemplateRepository _templateRepository; - private readonly ITableStyleRepository _tableStyleRepository; - private readonly IContentGroupRepository _contentGroupRepository; - private readonly IContentTagRepository _contentTagRepository; - public SiteRepository(ISettingsManager settingsManager, IChannelRepository channelRepository, IAdministratorRepository administratorRepository, ITemplateRepository templateRepository, ITableStyleRepository tableStyleRepository, IContentGroupRepository contentGroupRepository, IContentTagRepository contentTagRepository) + public SiteRepository(ISettingsManager settingsManager, IChannelRepository channelRepository, IAdministratorRepository administratorRepository, ITemplateRepository templateRepository) { _repository = new Repository(settingsManager.Database, settingsManager.Redis); + _settingsManager = settingsManager; _channelRepository = channelRepository; _administratorRepository = administratorRepository; _templateRepository = templateRepository; - _tableStyleRepository = tableStyleRepository; - _contentGroupRepository = contentGroupRepository; - _contentTagRepository = contentTagRepository; } public IDatabase Database => _repository.Database; @@ -71,15 +67,6 @@ public async Task InsertAsync(Site site) public async Task DeleteAsync(int siteId) { - var site = await GetAsync(siteId); - var list = await _channelRepository.GetChannelIdsAsync(siteId); - await _tableStyleRepository.DeleteAsync(list, site.TableName); - - await _contentGroupRepository.DeleteAsync(siteId); - await _contentTagRepository.DeleteAsync(siteId); - - await _channelRepository.DeleteAllAsync(siteId); - await UpdateParentIdToZeroAsync(siteId); await _repository.DeleteAsync(siteId, Q diff --git a/src/SSCMS.Core/Repositories/StatRepository.cs b/src/SSCMS.Core/Repositories/StatRepository.cs new file mode 100644 index 000000000..392ec384f --- /dev/null +++ b/src/SSCMS.Core/Repositories/StatRepository.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Datory; +using SSCMS.Enums; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; + +namespace SSCMS.Core.Repositories +{ + public class StatRepository : IStatRepository + { + private readonly Repository _repository; + + public StatRepository(ISettingsManager settingsManager) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + public async Task AddCountAsync(StatType statType, int siteId = 0) + { + var lowerDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day); + var higherDate = lowerDate.AddDays(1); + + var query = Q + .Where(nameof(Stat.SiteId), siteId) + .Where(nameof(Stat.StatType), statType.GetValue()) + .WhereBetween(nameof(Stat.CreatedDate), lowerDate, higherDate); + + if (await _repository.ExistsAsync(query)) + { + await _repository.IncrementAsync(nameof(Stat.Count), query); + } + else + { + await _repository.InsertAsync(new Stat + { + StatType = statType, + SiteId = siteId, + Count = 1 + }); + } + } + + public async Task> GetStatsAsync(DateTime lowerDate, DateTime higherDate, StatType statType, int siteId = 0) + { + var query = Q + .Where(nameof(Stat.StatType), statType.GetValue()) + .WhereBetween(nameof(Stat.CreatedDate), lowerDate, higherDate.AddDays(1)); + + if (siteId > 0) + { + query.Where(nameof(Stat.SiteId), siteId); + } + + return await _repository.GetAllAsync(query); + } + } +} diff --git a/src/SSCMS.Core/Repositories/TableStyleRepository.Cache.cs b/src/SSCMS.Core/Repositories/TableStyleRepository.Cache.cs index 4be8756f0..4a1300e5d 100644 --- a/src/SSCMS.Core/Repositories/TableStyleRepository.Cache.cs +++ b/src/SSCMS.Core/Repositories/TableStyleRepository.Cache.cs @@ -12,7 +12,7 @@ namespace SSCMS.Core.Repositories { public partial class TableStyleRepository { - public async Task> GetStylesAsync(string tableName, List relatedIdentities) + public async Task> GetTableStylesAsync(string tableName, List relatedIdentities, List excludeAttributeNames = null) { var allAttributeNames = new List(); var styleList = new List(); @@ -34,9 +34,9 @@ public async Task> GetStylesAsync(string tableName, List r } } - var userTableName = new Repository(_repository.Database).TableName; - var channelTableName = new Repository(_repository.Database).TableName; - var siteTableName = new Repository(_repository.Database).TableName; + var userTableName = _userRepository.TableName; + var channelTableName = _channelRepository.TableName; + var siteTableName = _siteRepository.TableName; if (tableName == userTableName || tableName == channelTableName || tableName == siteTableName) { @@ -46,10 +46,7 @@ public async Task> GetStylesAsync(string tableName, List r { nameof(User.DisplayName), nameof(User.Mobile), - nameof(User.Email), - nameof(User.Gender), - nameof(User.Birthday), - nameof(User.Bio) + nameof(User.Email) }; foreach (var columnName in tableStyleAttributes) @@ -65,6 +62,10 @@ public async Task> GetStylesAsync(string tableName, List r else { var excludeAttributeNameList = ColumnsManager.MetadataAttributes.Value; + if (excludeAttributeNames != null) + { + excludeAttributeNameList.AddRange(excludeAttributeNames); + } var list = await _repository.Database.GetTableColumnsAsync(tableName); if (excludeAttributeNameList != null && excludeAttributeNameList.Count > 0) @@ -91,28 +92,29 @@ public async Task> GetStylesAsync(string tableName, List r public async Task> GetSiteStylesAsync(int siteId) { var relatedIdentities = GetRelatedIdentities(siteId); - var siteTableName = new Repository(_repository.Database).TableName; - return await GetStylesAsync(siteTableName, relatedIdentities); + var siteTableName = _siteRepository.TableName; + return await GetTableStylesAsync(siteTableName, relatedIdentities); } public async Task> GetChannelStylesAsync(Channel channel) { var relatedIdentities = GetRelatedIdentities(channel); - var channelTableName = new Repository(_repository.Database).TableName; - return await GetStylesAsync(channelTableName, relatedIdentities); + var channelTableName = _channelRepository.TableName; + return await GetTableStylesAsync(channelTableName, relatedIdentities); } - public async Task> GetContentStylesAsync(Channel channel, string tableName) + public async Task> GetContentStylesAsync(Site site, Channel channel) { + var tableName = _channelRepository.GetTableName(site, channel); var relatedIdentities = GetRelatedIdentities(channel); - return await GetStylesAsync(tableName, relatedIdentities); + return await GetTableStylesAsync(tableName, relatedIdentities); } public async Task> GetUserStylesAsync() { var relatedIdentities = EmptyRelatedIdentities; - var userTableName = new Repository(_repository.Database).TableName; - return await GetStylesAsync(userTableName, relatedIdentities); + var userTableName = _userRepository.TableName; + return await GetTableStylesAsync(userTableName, relatedIdentities); } //relatedIdentities从大到小,最后是0 @@ -130,9 +132,9 @@ public async Task GetTableStyleAsync(string tableName, string attrib return style; } - var userTableName = new Repository(_repository.Database).TableName; - var channelTableName = new Repository(_repository.Database).TableName; - var siteTableName = new Repository(_repository.Database).TableName; + var userTableName = _userRepository.TableName; + var channelTableName = _channelRepository.TableName; + var siteTableName = _siteRepository.TableName; if (tableName == userTableName || tableName == channelTableName || tableName == siteTableName) { @@ -216,7 +218,7 @@ public List GetRelatedIdentities(Channel channel) private async Task GetMaxTaxisAsync(string tableName, List relatedIdentities) { - var list = await GetStylesAsync(tableName, relatedIdentities); + var list = await GetTableStylesAsync(tableName, relatedIdentities); if (list != null && list.Count > 0) { return list.Max(x => x.Taxis); @@ -409,40 +411,6 @@ private TableStyle GetDefaultUserTableStyle(string tableName, string attributeNa }); style.Taxis = 3; } - else if (StringUtils.EqualsIgnoreCase(attributeName, nameof(User.Gender))) - { - style.AttributeName = nameof(User.Gender); - style.DisplayName = "性别"; - style.InputType = InputType.Radio; - style.Items = new List - { - new InputStyleItem - { - Label = "男", - Value = "男" - }, - new InputStyleItem - { - Label = "女", - Value = "女" - } - }; - style.Taxis = 4; - } - else if (StringUtils.EqualsIgnoreCase(attributeName, nameof(User.Birthday))) - { - style.AttributeName = nameof(User.Birthday); - style.DisplayName = "出生日期"; - style.InputType = InputType.Date; - style.Taxis = 5; - } - else if (StringUtils.EqualsIgnoreCase(attributeName, nameof(User.Bio))) - { - style.AttributeName = nameof(User.Bio); - style.InputType = InputType.TextArea; - style.DisplayName = "个人简介"; - style.Taxis = 9; - } return style; } diff --git a/src/SSCMS.Core/Repositories/TableStyleRepository.cs b/src/SSCMS.Core/Repositories/TableStyleRepository.cs index 8f9b5dd58..7cc732e0d 100644 --- a/src/SSCMS.Core/Repositories/TableStyleRepository.cs +++ b/src/SSCMS.Core/Repositories/TableStyleRepository.cs @@ -14,10 +14,16 @@ namespace SSCMS.Core.Repositories public partial class TableStyleRepository : ITableStyleRepository { private readonly Repository _repository; + private readonly ISiteRepository _siteRepository; + private readonly IChannelRepository _channelRepository; + private readonly IUserRepository _userRepository; - public TableStyleRepository(ISettingsManager settingsManager) + public TableStyleRepository(ISettingsManager settingsManager, ISiteRepository siteRepository, IChannelRepository channelRepository, IUserRepository userRepository) { _repository = new Repository(settingsManager.Database, settingsManager.Redis); + _siteRepository = siteRepository; + _channelRepository = channelRepository; + _userRepository = userRepository; } public IDatabase Database => _repository.Database; @@ -37,6 +43,11 @@ private void Sync(TableStyle style) { style.ItemValues = TranslateUtils.JsonSerialize(style.Items); } + + if (style?.Rules != null) + { + style.RuleValues = TranslateUtils.JsonSerialize(style.Rules); + } } public async Task InsertAsync(List relatedIdentities, TableStyle style) @@ -72,23 +83,23 @@ await _repository.DeleteAsync(Q ); } - public async Task DeleteAsync(int relatedIdentity, string tableName, string attributeName) + public async Task DeleteAllAsync(string tableName, List relatedIdentities) { + if (relatedIdentities == null || relatedIdentities.Count <= 0) return; + await _repository.DeleteAsync(Q - .Where(nameof(TableStyle.RelatedIdentity), relatedIdentity) + .WhereIn(nameof(TableStyle.RelatedIdentity), relatedIdentities) .Where(nameof(TableStyle.TableName), tableName) - .Where(nameof(TableStyle.AttributeName), attributeName) .CachingRemove(GetCacheKey(tableName)) ); } - public async Task DeleteAsync(List relatedIdentities, string tableName) + public async Task DeleteAsync(string tableName, int relatedIdentity, string attributeName) { - if (relatedIdentities == null || relatedIdentities.Count <= 0) return; - await _repository.DeleteAsync(Q - .WhereIn(nameof(TableStyle.RelatedIdentity), relatedIdentities) + .Where(nameof(TableStyle.RelatedIdentity), relatedIdentity) .Where(nameof(TableStyle.TableName), tableName) + .Where(nameof(TableStyle.AttributeName), attributeName) .CachingRemove(GetCacheKey(tableName)) ); } @@ -103,6 +114,7 @@ private async Task> GetAllAsync(string tableName) foreach (var style in styles) { style.Items = TranslateUtils.JsonDeserialize>(style.ItemValues); + style.Rules = TranslateUtils.JsonDeserialize>(style.RuleValues); } return styles; diff --git a/src/SSCMS.Core/Repositories/TranslateRepository.cs b/src/SSCMS.Core/Repositories/TranslateRepository.cs new file mode 100644 index 000000000..013713168 --- /dev/null +++ b/src/SSCMS.Core/Repositories/TranslateRepository.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Datory; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; + +namespace SSCMS.Core.Repositories +{ + public class TranslateRepository : ITranslateRepository + { + private readonly Repository _repository; + private readonly ISiteRepository _siteRepository; + private readonly IChannelRepository _channelRepository; + + public TranslateRepository(ISettingsManager settingsManager, ISiteRepository siteRepository, IChannelRepository channelRepository) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + _siteRepository = siteRepository; + _channelRepository = channelRepository; + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + public async Task InsertAsync(Translate translate) + { + await _repository.InsertAsync(translate); + } + + public async Task DeleteAsync(int siteId, int channelId) + { + await _repository.DeleteAsync(Q + .Where(nameof(Translate.SiteId), siteId) + .Where(nameof(Translate.ChannelId), channelId) + ); + } + + public async Task> GetTranslatesAsync(int siteId, bool summary = false) + { + var translates = await _repository.GetAllAsync(Q + .Where(nameof(Translate.SiteId), siteId) + .OrderBy(nameof(Translate.Id)) + ); + + if (summary) + { + foreach (var translate in translates) + { + translate.Summary = await GetSummaryAsync(translate); + } + } + + return translates; + } + + public async Task> GetTranslatesAsync(int siteId, int channelId, bool summary = false) + { + var translates = await _repository.GetAllAsync(Q + .Where(nameof(Translate.SiteId), siteId) + .Where(nameof(Translate.ChannelId), channelId) + .OrderBy(nameof(Translate.Id)) + ); + + if (summary) + { + foreach (var translate in translates) + { + translate.Summary = await GetSummaryAsync(translate); + } + } + + return translates; + } + + public async Task GetSummaryAsync(Translate translate) + { + var name = await _channelRepository.GetChannelNameNavigationAsync(translate.TargetSiteId, translate.TargetChannelId); + if (string.IsNullOrEmpty(name)) return null; + + if (translate.TargetSiteId != translate.SiteId) + { + var site = await _siteRepository.GetAsync(translate.TargetSiteId); + if (site == null) return null; + + name = site.SiteName + " : " + name; + } + + name += $" ({translate.TranslateType.GetDisplayName()})"; + return name; + } + } +} \ No newline at end of file diff --git a/src/SSCMS.Core/Repositories/UserMenuRepository.cs b/src/SSCMS.Core/Repositories/UserMenuRepository.cs index f71206130..18ecf27ce 100644 --- a/src/SSCMS.Core/Repositories/UserMenuRepository.cs +++ b/src/SSCMS.Core/Repositories/UserMenuRepository.cs @@ -61,50 +61,57 @@ public async Task ResetAsync() var parentId = await InsertAsync(new UserMenu { - Text = "用户中心" + Text = "用户中心", + Taxis = 1 }); await InsertAsync(new UserMenu { ParentId = parentId, Text = "修改资料", - IconClass = "fa fa-edit", - Link = "/home/profile/" + IconClass = "ion-edit", + Link = "/home/profile/", + Taxis = 1 }); await InsertAsync(new UserMenu { ParentId = parentId, Text = "更改密码", - IconClass = "fa fa-lock", - Link = "/home/password/" + IconClass = "ion-locked", + Link = "/home/password/", + Taxis = 2 }); await InsertAsync(new UserMenu { ParentId = parentId, Text = "退出系统", - IconClass = "fa fa-sign-out", - Link = "/home/logout/" + IconClass = "ion-log-out", + Link = "/home/logout/", + Taxis = 3 }); - parentId = await InsertAsync(new UserMenu - { - Text = "投稿中心" - }); - - await InsertAsync(new UserMenu - { - ParentId = parentId, - Text = "新增稿件", - IconClass = "fa fa-plus", - Link = "/home/write/editor/" - }); - await InsertAsync(new UserMenu - { - ParentId = parentId, - Text = "稿件管理", - IconClass = "fa fa-list", - Link = "/home/write/contents/" - }); + //parentId = await InsertAsync(new UserMenu + //{ + // Text = "投稿中心", + // Taxis = 2 + //}); + + //await InsertAsync(new UserMenu + //{ + // ParentId = parentId, + // Text = "新增稿件", + // IconClass = "ion-plus", + // Link = "/home/write/editor/", + // Taxis = 1 + //}); + //await InsertAsync(new UserMenu + //{ + // ParentId = parentId, + // Text = "稿件管理", + // IconClass = "ion-document-text", + // Link = "/home/write/contents/", + // Taxis = 2 + //}); } } } diff --git a/src/SSCMS.Core/Repositories/UserRepository.Cache.cs b/src/SSCMS.Core/Repositories/UserRepository.Cache.cs index cc825becf..5e0a4b8dc 100644 --- a/src/SSCMS.Core/Repositories/UserRepository.Cache.cs +++ b/src/SSCMS.Core/Repositories/UserRepository.Cache.cs @@ -1,7 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; -using CacheManager.Core; using Datory; using SSCMS.Core.Utils; using SSCMS.Models; @@ -108,27 +106,23 @@ private static string GetIpAddressCacheKey(string ipAddress) return $"{nameof(UserRepository)}:{ipAddress}"; } - public async Task IsIpAddressCachedAsync(string ipAddress) + private async Task IsIpAddressCachedAsync(string ipAddress) { var config = await _configRepository.GetAsync(); if (config.UserRegistrationMinMinutes == 0 || string.IsNullOrEmpty(ipAddress)) { - return true; + return false; } - var cacheManager = await _repository.GetCacheManagerAsync(); - return cacheManager.Exists(GetIpAddressCacheKey(ipAddress)); + return _cacheManager.Exists(GetIpAddressCacheKey(ipAddress)); } - public async Task CacheIpAddressAsync(string ipAddress) + private async Task CacheIpAddressAsync(string ipAddress) { var config = await _configRepository.GetAsync(); if (config.UserRegistrationMinMinutes > 0 && !string.IsNullOrEmpty(ipAddress)) { - var cacheManager = await _repository.GetCacheManagerAsync(); - var value = new CacheItem(GetIpAddressCacheKey(ipAddress), true, ExpirationMode.Sliding, TimeSpan.FromMinutes(config.UserRegistrationMinMinutes)); - - cacheManager.AddOrUpdate(value, _ => value); + _cacheManager.AddOrUpdateAbsolute(GetIpAddressCacheKey(ipAddress), true, config.UserRegistrationMinMinutes); } } diff --git a/src/SSCMS.Core/Repositories/UserRepository.cs b/src/SSCMS.Core/Repositories/UserRepository.cs index 0eb2c078b..6bcf2389d 100644 --- a/src/SSCMS.Core/Repositories/UserRepository.cs +++ b/src/SSCMS.Core/Repositories/UserRepository.cs @@ -18,11 +18,13 @@ namespace SSCMS.Core.Repositories public partial class UserRepository : IUserRepository { private readonly Repository _repository; + private readonly ICacheManager _cacheManager; private readonly IConfigRepository _configRepository; - public UserRepository(ISettingsManager settingsManager, IConfigRepository configRepository) + public UserRepository(ISettingsManager settingsManager, ICacheManager cacheManager, IConfigRepository configRepository) { _repository = new Repository(settingsManager.Database, settingsManager.Redis); + _cacheManager = cacheManager; _configRepository = configRepository; } @@ -34,7 +36,7 @@ public UserRepository(ISettingsManager settingsManager, IConfigRepository config private async Task<(bool success, string errorMessage)> InsertValidateAsync(string userName, string email, string mobile, string password, string ipAddress) { var config = await _configRepository.GetAsync(); - if (!await IsIpAddressCachedAsync(ipAddress)) + if (await IsIpAddressCachedAsync(ipAddress)) { return (false, $"同一IP在{config.UserRegistrationMinMinutes}分钟内只能注册一次"); } @@ -245,14 +247,16 @@ private static string EncodePassword(string password, PasswordFormat passwordFor } else if (passwordFormat == PasswordFormat.Encrypted) { - var des = new DesEncryptor - { - InputString = password, - EncryptKey = passwordSalt - }; - des.DesEncrypt(); + retVal = TranslateUtils.EncryptStringBySecretKey(password, passwordSalt); + + //var des = new DesEncryptor + //{ + // InputString = password, + // EncryptKey = passwordSalt + //}; + //des.DesEncrypt(); - retVal = des.OutString; + //retVal = des.OutString; } return retVal; } @@ -270,14 +274,16 @@ private static string DecodePassword(string password, PasswordFormat passwordFor } else if (passwordFormat == PasswordFormat.Encrypted) { - var des = new DesEncryptor - { - InputString = password, - DecryptKey = passwordSalt - }; - des.DesDecrypt(); + retVal = TranslateUtils.DecryptStringBySecretKey(password, passwordSalt); + + //var des = new DesEncryptor + //{ + // InputString = password, + // DecryptKey = passwordSalt + //}; + //des.DesDecrypt(); - retVal = des.OutString; + //retVal = des.OutString; } return retVal; } diff --git a/src/SSCMS.Core/Repositories/WxAccountRepository.cs b/src/SSCMS.Core/Repositories/WxAccountRepository.cs new file mode 100644 index 000000000..64b7f55c0 --- /dev/null +++ b/src/SSCMS.Core/Repositories/WxAccountRepository.cs @@ -0,0 +1,58 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Datory; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; + +namespace SSCMS.Core.Repositories +{ + public class WxAccountRepository : IWxAccountRepository + { + private readonly Repository _repository; + + public WxAccountRepository(ISettingsManager settingsManager) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + public async Task SetAsync(WxAccount account) + { + if (account.SiteId <= 0) return; + + if (account.Id > 0) + { + await _repository.UpdateAsync(account); + } + else + { + await _repository.InsertAsync(account); + } + } + + public async Task DeleteBySiteIdAsync(int siteId) + { + await _repository.DeleteAsync(Q + .Where(nameof(WxAccount.SiteId), siteId) + ); + } + + public async Task GetBySiteIdAsync(int siteId) + { + var account = await _repository.GetAsync(Q + .Where(nameof(WxAccount.SiteId), siteId) + ) ?? new WxAccount + { + SiteId = siteId + }; + + return account; + } + } +} diff --git a/src/SSCMS.Core/Repositories/WxChatRepository.cs b/src/SSCMS.Core/Repositories/WxChatRepository.cs new file mode 100644 index 000000000..bb93f3ef2 --- /dev/null +++ b/src/SSCMS.Core/Repositories/WxChatRepository.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Datory; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; + +namespace SSCMS.Core.Repositories +{ + public class WxChatRepository : IWxChatRepository + { + private readonly Repository _repository; + + public WxChatRepository(ISettingsManager settingsManager) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + public async Task UserAdd(WxChat chat) + { + var isSession = await _repository.ExistsAsync(Q + .Where(nameof(WxChat.SiteId), chat.SiteId) + .Where(nameof(WxChat.OpenId), chat.OpenId) + .Where(nameof(WxChat.IsReply), true) + .WhereDate(nameof(WxChat.CreatedDate), ">", DateTime.Now.AddDays(-1)) + ); + + await _repository.InsertAsync(chat); + return isSession; + } + + public async Task ReplyAdd(WxChat chat) + { + await _repository.InsertAsync(chat); + } + + public async Task Star(int siteId, int chatId, bool star) + { + await _repository.UpdateAsync(Q. + Set(nameof(WxChat.IsStar), star) + .Where(nameof(WxChat.SiteId), siteId) + .Where(nameof(WxChat.Id), chatId) + ); + } + + public async Task DeleteAsync(int siteId, int chatId) + { + await _repository.DeleteAsync(Q + .Where(nameof(WxChat.Id), chatId) + ); + } + + public async Task DeleteAllAsync(int siteId, string openId) + { + await _repository.DeleteAsync(Q + .Where(nameof(WxChat.SiteId), siteId) + .Where(nameof(WxChat.OpenId), openId) + ); + } + + public async Task> GetChatsAsyncByOpenId(int siteId, string openId) + { + if (string.IsNullOrEmpty(openId)) return new List(); + return await _repository.GetAllAsync(Q + .Where(nameof(WxChat.SiteId), siteId) + .Where(nameof(WxChat.OpenId), openId) + .OrderByDesc(nameof(WxChat.Id)) + ); + } + + public async Task GetCountAsync(int siteId, bool star, string keyword) + { + var query = Q + .Where(nameof(WxChat.SiteId), siteId) + .Where(nameof(WxChat.IsReply), false); + if (star) + { + query.Where(nameof(WxChat.IsStar), true); + } + if (!string.IsNullOrEmpty(keyword)) + { + query.WhereLike(nameof(WxChat.Text), $"%{keyword}%"); + } + return await _repository.CountAsync(query); + } + + public async Task> GetChatsAsync(int siteId, bool star, string keyword, int page, int perPage) + { + var query = Q + .Where(nameof(WxChat.SiteId), siteId) + .Where(nameof(WxChat.IsReply), false) + .ForPage(page, perPage) + .OrderByDesc(nameof(WxChat.Id)); + if (star) + { + query.Where(nameof(WxChat.IsStar), true); + } + if (!string.IsNullOrEmpty(keyword)) + { + query.WhereLike(nameof(WxChat.Text), $"%{keyword}%"); + } + + return await _repository.GetAllAsync(query); + } + } +} diff --git a/src/SSCMS.Core/Repositories/WxMenuRepository.cs b/src/SSCMS.Core/Repositories/WxMenuRepository.cs new file mode 100644 index 000000000..b10826b79 --- /dev/null +++ b/src/SSCMS.Core/Repositories/WxMenuRepository.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; + +namespace SSCMS.Core.Repositories +{ + public class WxMenuRepository : IWxMenuRepository + { + private readonly Repository _repository; + + public WxMenuRepository(ISettingsManager settingsManager) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string GetCacheKey(int siteId) => CacheUtils.GetListKey(_repository.TableName, siteId); + + public async Task InsertAsync(WxMenu menu) + { + return await _repository.InsertAsync(menu, Q + .CachingRemove(GetCacheKey(menu.SiteId)) + ); + } + + public async Task UpdateAsync(WxMenu menu) + { + await _repository.UpdateAsync(menu, Q + .CachingRemove(GetCacheKey(menu.SiteId)) + ); + } + + public async Task DeleteAsync(int siteId, int menuId) + { + await _repository.DeleteAsync(menuId, Q + .CachingRemove(GetCacheKey(siteId)) + ); + } + + public async Task DeleteAllAsync(int siteId) + { + await _repository.DeleteAsync(Q + .Where(nameof(WxMenu.SiteId), siteId) + .CachingRemove(GetCacheKey(siteId)) + ); + } + + public async Task> GetMenusAsync(int siteId) + { + var list = await _repository.GetAllAsync(Q + .Where(nameof(WxReplyKeyword.SiteId), siteId) + .CachingGet(GetCacheKey(siteId)) + ); + + return list.OrderBy(menu => menu.Taxis == 0 ? int.MaxValue : menu.Taxis).ToList(); + } + + public async Task GetAsync(int siteId, int id) + { + var infoList = await _repository.GetAllAsync(Q + .CachingGet(GetCacheKey(siteId)) + ); + return infoList.FirstOrDefault(x => x.Id == id); + } + } +} diff --git a/src/SSCMS.Core/Repositories/WxReplyKeywordRepository.cs b/src/SSCMS.Core/Repositories/WxReplyKeywordRepository.cs new file mode 100644 index 000000000..3fd543612 --- /dev/null +++ b/src/SSCMS.Core/Repositories/WxReplyKeywordRepository.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; + +namespace SSCMS.Core.Repositories +{ + public class WxReplyKeywordRepository : IWxReplyKeywordRepository + { + private readonly Repository _repository; + + public WxReplyKeywordRepository(ISettingsManager settingsManager) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string GetCacheKey(int siteId) => CacheUtils.GetListKey(_repository.TableName, siteId); + + public async Task InsertAsync(WxReplyKeyword keyword) + { + return await _repository.InsertAsync(keyword, Q + .CachingRemove(GetCacheKey(keyword.SiteId)) + ); + } + + public async Task UpdateAsync(WxReplyKeyword keyword) + { + await _repository.UpdateAsync(keyword, Q + .CachingRemove(GetCacheKey(keyword.SiteId)) + ); + } + + public async Task DeleteAllAsync(int siteId, int ruleId) + { + await _repository.DeleteAsync(Q + .Where(nameof(WxReplyKeyword.SiteId), siteId) + .Where(nameof(WxReplyKeyword.RuleId), ruleId) + .CachingRemove(GetCacheKey(siteId)) + ); + } + + public async Task> GetKeywordsAsync(int siteId, int ruleId) + { + var allKeywords = await GetKeywordsAsync(siteId); + return allKeywords.Where(x => x.RuleId == ruleId).ToList(); + } + + public async Task> GetKeywordsAsync(int siteId) + { + return await _repository.GetAllAsync(Q + .Where(nameof(WxReplyKeyword.SiteId), siteId) + .CachingGet(GetCacheKey(siteId)) + ); + } + } +} diff --git a/src/SSCMS.Core/Repositories/WxReplyMessageRepository.cs b/src/SSCMS.Core/Repositories/WxReplyMessageRepository.cs new file mode 100644 index 000000000..66638f234 --- /dev/null +++ b/src/SSCMS.Core/Repositories/WxReplyMessageRepository.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; + +namespace SSCMS.Core.Repositories +{ + public class WxReplyMessageRepository : IWxReplyMessageRepository + { + private readonly Repository _repository; + + public WxReplyMessageRepository(ISettingsManager settingsManager) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string GetCacheKey(int siteId) => CacheUtils.GetListKey(_repository.TableName, siteId); + + public async Task InsertAsync(WxReplyMessage message) + { + return await _repository.InsertAsync(message, Q + .CachingRemove(GetCacheKey(message.SiteId)) + ); + } + + public async Task UpdateAsync(WxReplyMessage message) + { + await _repository.UpdateAsync(message, Q + .CachingRemove(GetCacheKey(message.SiteId)) + ); + } + + public async Task DeleteAllAsync(int siteId, int ruleId) + { + await _repository.DeleteAsync(Q + .Where(nameof(WxReplyMessage.SiteId), siteId) + .Where(nameof(WxReplyMessage.RuleId), ruleId) + .CachingRemove(GetCacheKey(siteId)) + ); + } + + public async Task> GetMessagesAsync(int siteId, int ruleId) + { + if (ruleId == 0) return new List(); + var allMessages = await GetAllAsync(siteId); + return allMessages.Where(x => x.RuleId == ruleId).ToList(); + } + + public async Task GetMessageAsync(int siteId, int messageId) + { + var allMessages = await GetAllAsync(siteId); + return allMessages.FirstOrDefault(x => x.Id == messageId); + } + + private async Task> GetAllAsync(int siteId) + { + return await _repository.GetAllAsync(Q + .Where(nameof(WxReplyKeyword.SiteId), siteId) + .CachingGet(GetCacheKey(siteId)) + ); + } + } +} diff --git a/src/SSCMS.Core/Repositories/WxReplyRuleRepository.cs b/src/SSCMS.Core/Repositories/WxReplyRuleRepository.cs new file mode 100644 index 000000000..214649186 --- /dev/null +++ b/src/SSCMS.Core/Repositories/WxReplyRuleRepository.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Datory; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; + +namespace SSCMS.Core.Repositories +{ + public class WxReplyRuleRepository : IWxReplyRuleRepository + { + private readonly Repository _repository; + + public WxReplyRuleRepository(ISettingsManager settingsManager) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + public async Task InsertAsync(WxReplyRule rule) + { + return await _repository.InsertAsync(rule); + } + + public async Task UpdateAsync(WxReplyRule rule) + { + await _repository.UpdateAsync(rule); + } + + public async Task DeleteAsync(int ruleId) + { + await _repository.DeleteAsync(ruleId); + } + + public async Task GetCount(int siteId, string keyword) + { + return await _repository.CountAsync(Q + .WhereLike(nameof(WxReplyRule.RuleName), $"%{keyword}%") + .Where(nameof(WxReplyRule.SiteId), siteId) + ); + } + + public async Task> GetRulesAsync(int siteId, string keyword, int page, int perPage) + { + return await _repository.GetAllAsync(Q + .Where(nameof(WxReplyRule.SiteId), siteId) + .WhereLike(nameof(WxReplyRule.RuleName), $"%{keyword}%") + .ForPage(page, perPage) + .OrderByDesc(nameof(WxReplyRule.Id)) + ); + } + + public async Task GetAsync(int ruleId) + { + return await _repository.GetAsync(ruleId); + } + } +} diff --git a/src/SSCMS.Core/Repositories/WxUserRepository.cs b/src/SSCMS.Core/Repositories/WxUserRepository.cs new file mode 100644 index 000000000..559364636 --- /dev/null +++ b/src/SSCMS.Core/Repositories/WxUserRepository.cs @@ -0,0 +1,113 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using SSCMS.Core.Utils; +using SSCMS.Models; +using SSCMS.Repositories; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Core.Repositories +{ + public class WxUserRepository : IWxUserRepository + { + private readonly Repository _repository; + + public WxUserRepository(ISettingsManager settingsManager) + { + _repository = new Repository(settingsManager.Database, settingsManager.Redis); + } + + public IDatabase Database => _repository.Database; + + public string TableName => _repository.TableName; + + public List TableColumns => _repository.TableColumns; + + private string GetCacheKey(int siteId) + { + return CacheUtils.GetListKey(_repository.TableName, siteId); + } + + public async Task InsertAsync(int siteId, WxUser user) + { + user.SiteId = siteId; + return await _repository.InsertAsync(user, Q + .CachingRemove(GetCacheKey(siteId)) + ); + } + + public async Task UpdateAllAsync(int siteId, List users) + { + var dbUsers = await GetAllAsync(siteId); + foreach (var user in users) + { + var dbUser = dbUsers.FirstOrDefault(x => x.OpenId == user.OpenId); + if (dbUser == null) continue; + + if (ListUtils.ToString(dbUser.TagIdList) != ListUtils.ToString(user.TagIdList) || + dbUser.Nickname != user.Nickname || + dbUser.Remark != user.Remark) + { + await _repository.UpdateAsync(Q + .Set(nameof(WxUser.TagIdList), ListUtils.ToString(user.TagIdList)) + .Set(nameof(WxUser.Nickname), user.Nickname) + .Set(nameof(WxUser.Remark), user.Remark) + .Where(nameof(WxUser.OpenId), user.OpenId) + .CachingRemove(GetCacheKey(siteId)) + ); + } + } + } + + public async Task DeleteAllAsync(int siteId, List openIds) + { + if (openIds == null || openIds.Count == 0) return; + + await _repository.DeleteAsync(Q + .WhereIn(nameof(WxUser.OpenId), openIds) + .Where(nameof(WxUser.SiteId), siteId) + .CachingRemove(GetCacheKey(siteId)) + ); + } + + private async Task> GetAllAsync(int siteId) + { + return await _repository.GetAllAsync(Q + .Where(nameof(WxUser.SiteId), siteId) + .OrderByDesc(nameof(WxUser.SubscribeTime)) + .CachingGet(GetCacheKey(siteId)) + ); + } + + public async Task<(int Total, int Count, List Results)> GetPageOpenIds(int siteId, int tagId, string keyword, int page, int perPage) + { + var users = await GetAllAsync(siteId); + var total = users.Count; + + if (tagId != 0) + { + users = users.Where(x => ListUtils.Contains(x.TagIdList, tagId)).ToList(); + } + + if (!string.IsNullOrEmpty(keyword)) + { + users = users.Where(x => + StringUtils.ContainsIgnoreCase(x.Nickname, keyword) || + StringUtils.ContainsIgnoreCase(x.Remark, keyword)).ToList(); + } + + var count = users.Count; + + var results = users.Skip((page - 1) * perPage).Take(perPage).Select(x => x.OpenId).ToList(); + return (total, count, results); + } + + public async Task> GetAllOpenIds(int siteId) + { + var users = await GetAllAsync(siteId); + return users.Select(x => x.OpenId).ToList(); + } + } +} diff --git a/src/SSCMS.Core/SSCMS.Core.csproj b/src/SSCMS.Core/SSCMS.Core.csproj index bdd17bbef..2d83b6108 100644 --- a/src/SSCMS.Core/SSCMS.Core.csproj +++ b/src/SSCMS.Core/SSCMS.Core.csproj @@ -10,7 +10,6 @@ - @@ -20,6 +19,7 @@ + @@ -28,12 +28,15 @@ - - - - - + + + + + + + + diff --git a/src/SSCMS.Core/Services/AuthManager.Jwt.cs b/src/SSCMS.Core/Services/AuthManager.Jwt.cs index 21f559491..bbc356f05 100644 --- a/src/SSCMS.Core/Services/AuthManager.Jwt.cs +++ b/src/SSCMS.Core/Services/AuthManager.Jwt.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using Microsoft.IdentityModel.Tokens; +using SSCMS.Configuration; using SSCMS.Models; using SSCMS.Utils; @@ -16,10 +17,10 @@ private ClaimsIdentity GetAdministratorIdentity(Administrator administrator, boo { return new ClaimsIdentity(new[] { - new Claim(AuthTypes.Claims.UserId, administrator.Id.ToString()), - new Claim(AuthTypes.Claims.UserName, administrator.UserName), - new Claim(AuthTypes.Claims.Role, AuthTypes.Roles.Administrator), - new Claim(AuthTypes.Claims.IsPersistent, isPersistent.ToString()) + new Claim(Types.Claims.UserId, administrator.Id.ToString()), + new Claim(Types.Claims.UserName, administrator.UserName), + new Claim(Types.Claims.Role, Types.Roles.Administrator), + new Claim(Types.Claims.IsPersistent, isPersistent.ToString()) }); } @@ -76,7 +77,7 @@ public async Task RefreshAdministratorTokenAsync(string accessToken) throw new SecurityTokenException("Invalid token passed!"); } - var isPersistent = TranslateUtils.ToBool(_principal.Claims.SingleOrDefault(c => c.Type == AuthTypes.Claims.IsPersistent)?.Value); + var isPersistent = TranslateUtils.ToBool(_principal.Claims.SingleOrDefault(c => c.Type == Types.Claims.IsPersistent)?.Value); var administrator = await _databaseManager.AdministratorRepository.GetByUserNameAsync(principal.Identity.Name); return AuthenticateAdministrator(administrator, isPersistent); @@ -86,10 +87,10 @@ private ClaimsIdentity GetUserIdentity(User user, bool isPersistent) { return new ClaimsIdentity(new[] { - new Claim(AuthTypes.Claims.UserId, user.Id.ToString()), - new Claim(AuthTypes.Claims.UserName, user.UserName), - new Claim(AuthTypes.Claims.Role, AuthTypes.Roles.User), - new Claim(AuthTypes.Claims.IsPersistent, isPersistent.ToString()) + new Claim(Types.Claims.UserId, user.Id.ToString()), + new Claim(Types.Claims.UserName, user.UserName), + new Claim(Types.Claims.Role, Types.Roles.User), + new Claim(Types.Claims.IsPersistent, isPersistent.ToString()) }); } @@ -146,80 +147,10 @@ public async Task RefreshUserTokenAsync(string accessToken) throw new SecurityTokenException("Invalid token passed!"); } - var isPersistent = TranslateUtils.ToBool(_principal.Claims.SingleOrDefault(c => c.Type == AuthTypes.Claims.IsPersistent)?.Value); + var isPersistent = TranslateUtils.ToBool(_principal.Claims.SingleOrDefault(c => c.Type == Types.Claims.IsPersistent)?.Value); var user = await _databaseManager.UserRepository.GetByUserNameAsync(principal.Identity.Name); return AuthenticateUser(user, isPersistent); } - - private ClaimsIdentity GetApiIdentity(AccessToken accessToken, bool isPersistent) - { - return new ClaimsIdentity(new[] - { - new Claim(AuthTypes.Claims.UserId, accessToken.Id.ToString()), - new Claim(AuthTypes.Claims.UserName, accessToken.Token), - new Claim(AuthTypes.Claims.Role, AuthTypes.Roles.Api), - new Claim(AuthTypes.Claims.IsPersistent, isPersistent.ToString()) - }); - } - - public string AuthenticateApi(AccessToken accessToken, bool isPersistent) - { - var tokenHandler = new JwtSecurityTokenHandler(); - var key = Encoding.ASCII.GetBytes(_settingsManager.SecurityKey); - SecurityTokenDescriptor tokenDescriptor; - var identity = GetApiIdentity(accessToken, isPersistent); - - if (isPersistent) - { - tokenDescriptor = new SecurityTokenDescriptor - { - Subject = identity, - Expires = DateTime.Now.AddDays(Constants.AccessTokenExpireDays), - SigningCredentials = new SigningCredentials( - new SymmetricSecurityKey(key), - SecurityAlgorithms.HmacSha256Signature) - }; - } - else - { - tokenDescriptor = new SecurityTokenDescriptor - { - Subject = identity, - Expires = DateTime.Now.AddDays(1), - SigningCredentials = new SigningCredentials( - new SymmetricSecurityKey(key), - SecurityAlgorithms.HmacSha256Signature) - }; - } - - var token = tokenHandler.CreateToken(tokenDescriptor); - - return tokenHandler.WriteToken(token); - } - - public async Task RefreshApiTokenAsync(string accessToken) - { - var tokenHandler = new JwtSecurityTokenHandler(); - var key = Encoding.ASCII.GetBytes(_settingsManager.SecurityKey); - var principal = tokenHandler.ValidateToken(accessToken, - new TokenValidationParameters - { - ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey(key), - ValidateIssuer = false, - ValidateAudience = false - }, out var validatedToken); - var jwtToken = validatedToken as JwtSecurityToken; - if (jwtToken == null || !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase)) - { - throw new SecurityTokenException("Invalid token passed!"); - } - - var isPersistent = TranslateUtils.ToBool(_principal.Claims.SingleOrDefault(c => c.Type == AuthTypes.Claims.IsPersistent)?.Value); - - var entity = await _databaseManager.AccessTokenRepository.GetByTokenAsync(principal.Identity.Name); - return AuthenticateApi(entity, isPersistent); - } } } diff --git a/src/SSCMS.Core/Services/AuthManager.Permissions.cs b/src/SSCMS.Core/Services/AuthManager.Permissions.cs index 48edaf778..d0a2576be 100644 --- a/src/SSCMS.Core/Services/AuthManager.Permissions.cs +++ b/src/SSCMS.Core/Services/AuthManager.Permissions.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Datory; +using SSCMS.Configuration; using SSCMS.Core.Utils; using SSCMS.Enums; using SSCMS.Utils; @@ -63,16 +64,64 @@ public async Task> GetSiteIdsAsync() { var dict = await GetSitePermissionDictAsync(); - foreach (var siteId in dict.Keys) + foreach (var siteId in dict.Keys.Where(siteId => !siteIdList.Contains(siteId))) { - if (!siteIdList.Contains(siteId)) + siteIdList.Add(siteId); + } + } + + return siteIdList; + } + + public async Task> GetChannelIdsAsync(int siteId) + { + if (await IsSiteAdminAsync(siteId)) + { + return await _databaseManager.ChannelRepository.GetChannelIdsAsync(siteId); + } + + var siteChannelIdList = new List(); + var dict = await GetChannelPermissionDictAsync(); + foreach (var dictKey in dict.Keys) + { + var kvp = ParsePermissionDictKey(dictKey); + if (kvp.Key == siteId) + { + var theChannelId = kvp.Value; + + var channelIdList = await _databaseManager.ChannelRepository.GetChannelIdsAsync(siteId, theChannelId, ScopeType.All); + + foreach (var channelId in channelIdList) { - siteIdList.Add(siteId); + if (!siteChannelIdList.Contains(channelId)) + { + siteChannelIdList.Add(channelId); + } } } } - return siteIdList; + return siteChannelIdList; + } + + public async Task> GetVisibleChannelIdsAsync(List channelIdsWithPermissions) + { + var visibleChannelIds = new List(); + foreach (var enabledChannelId in channelIdsWithPermissions) + { + var enabledChannel = await _databaseManager.ChannelRepository.GetAsync(enabledChannelId); + var parentIds = ListUtils.GetIntList(enabledChannel.ParentsPath); + foreach (var parentId in parentIds.Where(parentId => !visibleChannelIds.Contains(parentId))) + { + visibleChannelIds.Add(parentId); + } + if (!visibleChannelIds.Contains(enabledChannelId)) + { + visibleChannelIds.Add(enabledChannelId); + } + } + + return visibleChannelIds; } public async Task> GetChannelIdsAsync(int siteId, params string[] permissions) @@ -125,14 +174,14 @@ public async Task> GetAppPermissionsAsync() if (_databaseManager.RoleRepository.IsConsoleAdministrator(roles)) { appPermissions.AddRange(_permissions - .Where(x => StringUtils.EqualsIgnoreCase(x.Type, AuthTypes.Resources.App)) + .Where(x => ListUtils.ContainsIgnoreCase(x.Type, Types.Resources.App)) .Select(permission => permission.Id)); } else if (_databaseManager.RoleRepository.IsSystemAdministrator(roles)) { appPermissions = new List { - AuthTypes.AppPermissions.SettingsAdministrators + Types.AppPermissions.SettingsAdministrators }; } else @@ -317,8 +366,9 @@ private async Task>> GetSitePermissionDictAsync() foreach (var siteId in siteIdList) { var site = await _databaseManager.SiteRepository.GetAsync(siteId); + var siteType = _settingsManager.GetSiteType(site.SiteType).Id; var sitePermissions = _permissions - .Where(x => StringUtils.EqualsIgnoreCase(x.Type, site.SiteType)) + .Where(x => ListUtils.ContainsIgnoreCase(x.Type, siteType)) .Select(permission => permission.Id).ToList(); sitePermissionDict[siteId] = sitePermissions; @@ -345,7 +395,7 @@ private async Task>> GetChannelPermissionDictAsy if (_databaseManager.RoleRepository.IsSystemAdministrator(roles)) { var allContentPermissionList = _permissions - .Where(x => StringUtils.EqualsIgnoreCase(x.Type, AuthTypes.Resources.SiteChannel)) + .Where(x => ListUtils.ContainsIgnoreCase(x.Type, Types.Resources.Channel)) .Select(permission => permission.Id).ToList(); var siteIdList = await GetSiteIdsAsync(); @@ -375,7 +425,7 @@ private async Task>> GetContentPermissionDictAsy if (_databaseManager.RoleRepository.IsSystemAdministrator(roles)) { var allContentPermissionList = _permissions - .Where(x => StringUtils.EqualsIgnoreCase(x.Type, AuthTypes.Resources.SiteChannel)) + .Where(x => ListUtils.ContainsIgnoreCase(x.Type, Types.Resources.Channel)) .Select(permission => permission.Id).ToList(); var siteIdList = await GetSiteIdsAsync(); diff --git a/src/SSCMS.Core/Services/AuthManager.cs b/src/SSCMS.Core/Services/AuthManager.cs index f05e2fb54..71aa33995 100644 --- a/src/SSCMS.Core/Services/AuthManager.cs +++ b/src/SSCMS.Core/Services/AuthManager.cs @@ -12,17 +12,19 @@ namespace SSCMS.Core.Services { public partial class AuthManager : IAuthManager { + private readonly IHttpContextAccessor _context; private readonly ClaimsPrincipal _principal; private readonly ISettingsManager _settingsManager; private readonly IDatabaseManager _databaseManager; private readonly List _permissions; - public AuthManager(IHttpContextAccessor context, ISettingsManager settingsManager, IPluginManager pluginManager, IDatabaseManager databaseManager) + public AuthManager(IHttpContextAccessor context, ISettingsManager settingsManager, IDatabaseManager databaseManager) { + _context = context; _principal = context.HttpContext.User; _settingsManager = settingsManager; _databaseManager = databaseManager; - _permissions = pluginManager.GetPermissions(); + _permissions = _settingsManager.GetPermissions(); } private Administrator _admin; @@ -84,7 +86,7 @@ public async Task GetAdminAsync() return _admin; } - public bool IsAdmin => _principal != null && _principal.IsInRole(AuthTypes.Roles.Administrator); + public bool IsAdmin => _principal != null && _principal.IsInRole(Types.Roles.Administrator); public int AdminId => IsAdmin ? TranslateUtils.ToInt(_principal.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value) @@ -92,7 +94,7 @@ public async Task GetAdminAsync() public string AdminName => IsAdmin ? _principal.Identity.Name : string.Empty; - public bool IsUser => _principal != null && _principal.IsInRole(AuthTypes.Roles.User); + public bool IsUser => _principal != null && _principal.IsInRole(Types.Roles.User); public int UserId => IsUser ? TranslateUtils.ToInt(_principal.Claims.SingleOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value) @@ -100,8 +102,35 @@ public async Task GetAdminAsync() public string UserName => IsUser ? _principal.Identity.Name : string.Empty; - public bool IsApi => _principal != null && _principal.IsInRole(AuthTypes.Roles.Api); + //public bool IsApi => _principal != null && _principal.IsInRole(Types.Roles.Api); - public string ApiToken => IsApi ? _principal.Identity.Name : string.Empty; + //public string ApiToken => IsApi ? _principal.Identity.Name : string.Empty; + + public bool IsApi => ApiToken != null; + + public string ApiToken + { + get + { + if (_context.HttpContext.Request.Query.TryGetValue("apiKey", out var queries)) + { + var token = queries.SingleOrDefault(); + if (!string.IsNullOrWhiteSpace(token)) + { + return token; + } + } + if (_context.HttpContext.Request.Headers.TryGetValue("X-SS-API-KEY", out var headers)) + { + var token = headers.SingleOrDefault(); + if (!string.IsNullOrWhiteSpace(token)) + { + return token; + } + } + + return null; + } + } } } \ No newline at end of file diff --git a/src/SSCMS.Core/Services/CacheManager.Get.cs b/src/SSCMS.Core/Services/CacheManager.Get.cs new file mode 100644 index 000000000..d960a2507 --- /dev/null +++ b/src/SSCMS.Core/Services/CacheManager.Get.cs @@ -0,0 +1,15 @@ +namespace SSCMS.Core.Services +{ + public partial class CacheManager + { + public TCacheValue Get(string key) + { + return _cacheManager.Get(key); + } + + public bool Exists(string key) + { + return _cacheManager.Exists(key); + } + } +} diff --git a/src/SSCMS.Core/Services/CacheManager.Remove.cs b/src/SSCMS.Core/Services/CacheManager.Remove.cs new file mode 100644 index 000000000..a19f87e46 --- /dev/null +++ b/src/SSCMS.Core/Services/CacheManager.Remove.cs @@ -0,0 +1,15 @@ +namespace SSCMS.Core.Services +{ + public partial class CacheManager + { + public void Remove(string key) + { + _cacheManager.Remove(key); + } + + public void Clear() + { + _cacheManager.Clear(); + } + } +} diff --git a/src/SSCMS.Core/Services/CacheManager.Set.cs b/src/SSCMS.Core/Services/CacheManager.Set.cs new file mode 100644 index 000000000..45e26b9af --- /dev/null +++ b/src/SSCMS.Core/Services/CacheManager.Set.cs @@ -0,0 +1,58 @@ +using System; +using System.IO; +using CacheManager.Core; +using SSCMS.Core.Utils; +using SSCMS.Utils; + +namespace SSCMS.Core.Services +{ + public partial class CacheManager + { + public void AddOrUpdateSliding(string key, TCacheValue value, int minutes) + { + var cacheItem = new CacheItem(key, value, ExpirationMode.Sliding, TimeSpan.FromMinutes(minutes)); + _cacheManager.AddOrUpdate(cacheItem, _ => value); + } + + public void AddOrUpdateAbsolute(string key, TCacheValue value, int minutes) + { + var cacheItem = new CacheItem(key, value, ExpirationMode.Absolute, TimeSpan.FromMinutes(minutes)); + _cacheManager.AddOrUpdate(cacheItem, _ => value); + } + + public void AddOrUpdate(string key, TCacheValue value) + { + _cacheManager.AddOrUpdate(key, value, _ => value); + } + + public void AddOrUpdateFileWatcher(string filePath, TCacheValue value) + { + if (string.IsNullOrEmpty(filePath)) return; + var directoryPath = DirectoryUtils.GetDirectoryPath(filePath); + var fileName = PathUtils.GetFileName(filePath); + var watcher = new FileSystemWatcher + { + Filter = fileName, + Path = directoryPath, + EnableRaisingEvents = true + }; + + var cacheKey = CacheUtils.GetPathKey(filePath); + + watcher.Changed += (sender, e) => + { + Remove(cacheKey); + }; + watcher.Renamed += (sender, e) => + { + Remove(cacheKey); + }; + watcher.Deleted += (sender, e) => + { + Remove(cacheKey); + }; + + AddOrUpdateSliding(cacheKey, value, 12 * 60); + } + } +} diff --git a/src/SSCMS.Core/Services/CacheManager.cs b/src/SSCMS.Core/Services/CacheManager.cs new file mode 100644 index 000000000..7414f86be --- /dev/null +++ b/src/SSCMS.Core/Services/CacheManager.cs @@ -0,0 +1,16 @@ +using CacheManager.Core; + +namespace SSCMS.Core.Services +{ + public partial class CacheManager : SSCMS.Services.ICacheManager + { + private readonly ICacheManager _cacheManager; + + public CacheManager(ICacheManager cacheManager) + { + _cacheManager = cacheManager; + } + + public IReadOnlyCacheManagerConfiguration Configuration => _cacheManager.Configuration; + } +} diff --git a/src/SSCMS.Core/Services/CreateManager.Execute.cs b/src/SSCMS.Core/Services/CreateManager.Execute.cs index 5b77f4a45..0fd0245f7 100644 --- a/src/SSCMS.Core/Services/CreateManager.Execute.cs +++ b/src/SSCMS.Core/Services/CreateManager.Execute.cs @@ -1,6 +1,7 @@ using System; using System.Text; using System.Threading.Tasks; +using SSCMS.Configuration; using SSCMS.Core.StlParser.StlElement; using SSCMS.Core.StlParser.Utility; using SSCMS.Core.Utils; @@ -417,7 +418,7 @@ private async Task ExecuteFileAsync(int siteId, int fileTemplateId) await _parseManager.InitAsync(site, siteId, 0, templateInfo); - var filePath = await _pathManager.MapPathAsync(site, templateInfo.CreatedFileFullName); + var filePath = await _pathManager.ParseSitePathAsync(site, templateInfo.CreatedFileFullName); var contentBuilder = new StringBuilder(await _pathManager.GetTemplateContentAsync(site, templateInfo)); await _parseManager.ParseAsync(contentBuilder, filePath, false); @@ -433,7 +434,7 @@ private async Task ExecuteSpecialAsync(int siteId, int specialId) { await _parseManager.InitAsync(site, siteId, 0, templateInfo); - var filePath = await _pathManager.MapPathAsync(site, templateInfo.CreatedFileFullName); + var filePath = await _pathManager.ParseSitePathAsync(site, templateInfo.CreatedFileFullName); var contentBuilder = new StringBuilder(templateInfo.Content); await _parseManager.ParseAsync(contentBuilder, filePath, false); diff --git a/src/SSCMS.Core/Services/CreateManager.Task.cs b/src/SSCMS.Core/Services/CreateManager.Task.cs index 6b016a9a7..8671168f6 100644 --- a/src/SSCMS.Core/Services/CreateManager.Task.cs +++ b/src/SSCMS.Core/Services/CreateManager.Task.cs @@ -111,7 +111,7 @@ public void ClearAllTask(int siteId) lock (LockObject) { var pendingTasks = new List(); - foreach (var createTaskInfo in PendingTasks) + foreach (var createTaskInfo in PendingTasks.ToArray()) { if (createTaskInfo.SiteId != siteId) { @@ -132,7 +132,7 @@ public CreateTaskSummary GetTaskSummary(int siteId) var filesCount = 0; var specialsCount = 0; - foreach (var taskInfo in PendingTasks) + foreach (var taskInfo in PendingTasks.ToArray()) { if (taskInfo.SiteId != siteId) continue; diff --git a/src/SSCMS.Core/Services/DatabaseManager.Metadata.cs b/src/SSCMS.Core/Services/DatabaseManager.Metadata.cs index 6df4e0d87..ce9846c5d 100644 --- a/src/SSCMS.Core/Services/DatabaseManager.Metadata.cs +++ b/src/SSCMS.Core/Services/DatabaseManager.Metadata.cs @@ -4,18 +4,17 @@ using Datory; using SSCMS.Core.Utils; using SSCMS.Models; -using SSCMS.Services; using SSCMS.Utils; namespace SSCMS.Core.Services { public partial class DatabaseManager { - public async Task<(bool success, string errorMessage)> InstallAsync(IOldPluginManager pluginManager, string userName, string password, string email, string mobile) + public async Task<(bool success, string errorMessage)> InstallAsync(string userName, string password, string email, string mobile) { try { - await SyncDatabaseAsync(pluginManager); + await SyncDatabaseAsync(); var administrator = new Administrator { @@ -53,7 +52,7 @@ public async Task CreateSiteServerTablesAsync() } } - public async Task SyncDatabaseAsync(IOldPluginManager pluginManager) + public async Task SyncDatabaseAsync() { var repositories = GetAllRepositories(); @@ -77,14 +76,14 @@ public async Task SyncDatabaseAsync(IOldPluginManager pluginManager) await ConfigRepository.InsertAsync(config); } - await SyncContentTablesAsync(pluginManager); + await SyncContentTablesAsync(); await UpdateConfigVersionAsync(); } - public async Task SyncContentTablesAsync(IOldPluginManager pluginManager) + public async Task SyncContentTablesAsync() { - var tableNameList = await SiteRepository.GetAllTableNamesAsync(pluginManager); + var tableNameList = await SiteRepository.GetAllTableNamesAsync(); foreach (var tableName in tableNameList) { diff --git a/src/SSCMS.Core/Services/DatabaseManager.cs b/src/SSCMS.Core/Services/DatabaseManager.cs index 7da0b1cc6..b25e37684 100644 --- a/src/SSCMS.Core/Services/DatabaseManager.cs +++ b/src/SSCMS.Core/Services/DatabaseManager.cs @@ -18,8 +18,8 @@ public partial class DatabaseManager : IDatabaseManager public IAccessTokenRepository AccessTokenRepository { get; } public IAdministratorRepository AdministratorRepository { get; } public IAdministratorsInRolesRepository AdministratorsInRolesRepository { get; } - public IChannelGroupRepository ChannelGroupRepository { get; } public IChannelRepository ChannelRepository { get; } + public IChannelGroupRepository ChannelGroupRepository { get; } public IConfigRepository ConfigRepository { get; } public IContentCheckRepository ContentCheckRepository { get; } public IContentGroupRepository ContentGroupRepository { get; } @@ -27,12 +27,15 @@ public partial class DatabaseManager : IDatabaseManager public IContentTagRepository ContentTagRepository { get; } public IDbCacheRepository DbCacheRepository { get; } public IErrorLogRepository ErrorLogRepository { get; } - public ILibraryFileRepository LibraryFileRepository { get; } - public ILibraryGroupRepository LibraryGroupRepository { get; } - public ILibraryImageRepository LibraryImageRepository { get; } - public ILibraryTextRepository LibraryTextRepository { get; } - public ILibraryVideoRepository LibraryVideoRepository { get; } public ILogRepository LogRepository { get; } + public IMaterialArticleRepository MaterialArticleRepository { get; } + public IMaterialAudioRepository MaterialAudioRepository { get; } + public IMaterialFileRepository MaterialFileRepository { get; } + public IMaterialGroupRepository MaterialGroupRepository { get; } + public IMaterialImageRepository MaterialImageRepository { get; } + public IMaterialMessageRepository MaterialMessageRepository { get; } + public IMaterialMessageItemRepository MaterialMessageItemRepository { get; } + public IMaterialVideoRepository MaterialVideoRepository { get; } public IPermissionsInRolesRepository PermissionsInRolesRepository { get; } public IPluginConfigRepository PluginConfigRepository { get; } public IRelatedFieldItemRepository RelatedFieldItemRepository { get; } @@ -42,21 +45,30 @@ public partial class DatabaseManager : IDatabaseManager public ISitePermissionsRepository SitePermissionsRepository { get; } public ISiteRepository SiteRepository { get; } public ISpecialRepository SpecialRepository { get; } + public IStatRepository StatRepository { get; } public ITableStyleRepository TableStyleRepository { get; } public ITemplateLogRepository TemplateLogRepository { get; } public ITemplateRepository TemplateRepository { get; } + public ITranslateRepository TranslateRepository { get; } public IUserGroupRepository UserGroupRepository { get; } public IUserMenuRepository UserMenuRepository { get; } public IUserRepository UserRepository { get; } - - public DatabaseManager(ISettingsManager settingsManager, IAccessTokenRepository accessTokenRepository, IAdministratorRepository administratorRepository, IAdministratorsInRolesRepository administratorsInRolesRepository, IChannelGroupRepository channelGroupRepository, IChannelRepository channelRepository, IConfigRepository configRepository, IContentCheckRepository contentCheckRepository, IContentGroupRepository contentGroupRepository, IContentRepository contentRepository, IContentTagRepository contentTagRepository, IDbCacheRepository dbCacheRepository, IErrorLogRepository errorLogRepository, ILibraryFileRepository libraryFileRepository, ILibraryGroupRepository libraryGroupRepository, ILibraryImageRepository libraryImageRepository, ILibraryTextRepository libraryTextRepository, ILibraryVideoRepository libraryVideoRepository, ILogRepository logRepository, IPermissionsInRolesRepository permissionsInRolesRepository, IPluginConfigRepository pluginConfigRepository, IRelatedFieldItemRepository relatedFieldItemRepository, IRelatedFieldRepository relatedFieldRepository, IRoleRepository roleRepository, ISiteLogRepository siteLogRepository, ISitePermissionsRepository sitePermissionsRepository, ISiteRepository siteRepository, ISpecialRepository specialRepository, ITableStyleRepository tableStyleRepository, ITemplateLogRepository templateLogRepository, ITemplateRepository templateRepository, IUserGroupRepository userGroupRepository, IUserMenuRepository userMenuRepository, IUserRepository userRepository) + public IWxAccountRepository WxAccountRepository { get; } + public IWxChatRepository WxChatRepository { get; set; } + public IWxMenuRepository WxMenuRepository { get; } + public IWxReplyKeywordRepository WxReplyKeywordRepository { get; } + public IWxReplyMessageRepository WxReplyMessageRepository { get; } + public IWxReplyRuleRepository WxReplyRuleRepository { get; } + public IWxUserRepository WxUserRepository { get; } + + public DatabaseManager(ISettingsManager settingsManager, IAccessTokenRepository accessTokenRepository, IAdministratorRepository administratorRepository, IAdministratorsInRolesRepository administratorsInRolesRepository, IChannelRepository channelRepository, IChannelGroupRepository channelGroupRepository, IConfigRepository configRepository, IContentCheckRepository contentCheckRepository, IContentGroupRepository contentGroupRepository, IContentRepository contentRepository, IContentTagRepository contentTagRepository, IDbCacheRepository dbCacheRepository, IErrorLogRepository errorLogRepository, ILogRepository logRepository, IMaterialArticleRepository materialArticleRepository, IMaterialAudioRepository materialAudioRepository, IMaterialFileRepository materialFileRepository, IMaterialGroupRepository materialGroupRepository, IMaterialImageRepository materialImageRepository, IMaterialMessageRepository materialMessageRepository, IMaterialMessageItemRepository materialMessageItemRepository, IMaterialVideoRepository materialVideoRepository, IPermissionsInRolesRepository permissionsInRolesRepository, IPluginConfigRepository pluginConfigRepository, IRelatedFieldItemRepository relatedFieldItemRepository, IRelatedFieldRepository relatedFieldRepository, IRoleRepository roleRepository, ISiteLogRepository siteLogRepository, ISitePermissionsRepository sitePermissionsRepository, ISiteRepository siteRepository, ISpecialRepository specialRepository, IStatRepository statRepository, ITableStyleRepository tableStyleRepository, ITemplateLogRepository templateLogRepository, ITemplateRepository templateRepository, ITranslateRepository translateRepository, IUserGroupRepository userGroupRepository, IUserMenuRepository userMenuRepository, IUserRepository userRepository, IWxAccountRepository wxAccountRepository, IWxChatRepository wxChatRepository, IWxMenuRepository wxMenuRepository, IWxReplyKeywordRepository wxReplyKeywordRepository, IWxReplyMessageRepository wxReplyMessageRepository, IWxReplyRuleRepository wxReplyRuleRepository, IWxUserRepository wxUserRepository) { _settingsManager = settingsManager; AccessTokenRepository = accessTokenRepository; AdministratorRepository = administratorRepository; AdministratorsInRolesRepository = administratorsInRolesRepository; - ChannelGroupRepository = channelGroupRepository; ChannelRepository = channelRepository; + ChannelGroupRepository = channelGroupRepository; ConfigRepository = configRepository; ContentCheckRepository = contentCheckRepository; ContentGroupRepository = contentGroupRepository; @@ -64,12 +76,15 @@ public DatabaseManager(ISettingsManager settingsManager, IAccessTokenRepository ContentTagRepository = contentTagRepository; DbCacheRepository = dbCacheRepository; ErrorLogRepository = errorLogRepository; - LibraryFileRepository = libraryFileRepository; - LibraryGroupRepository = libraryGroupRepository; - LibraryImageRepository = libraryImageRepository; - LibraryTextRepository = libraryTextRepository; - LibraryVideoRepository = libraryVideoRepository; LogRepository = logRepository; + MaterialArticleRepository = materialArticleRepository; + MaterialAudioRepository = materialAudioRepository; + MaterialFileRepository = materialFileRepository; + MaterialGroupRepository = materialGroupRepository; + MaterialImageRepository = materialImageRepository; + MaterialMessageRepository = materialMessageRepository; + MaterialMessageItemRepository = materialMessageItemRepository; + MaterialVideoRepository = materialVideoRepository; PermissionsInRolesRepository = permissionsInRolesRepository; PluginConfigRepository = pluginConfigRepository; RelatedFieldItemRepository = relatedFieldItemRepository; @@ -79,12 +94,21 @@ public DatabaseManager(ISettingsManager settingsManager, IAccessTokenRepository SitePermissionsRepository = sitePermissionsRepository; SiteRepository = siteRepository; SpecialRepository = specialRepository; + StatRepository = statRepository; TableStyleRepository = tableStyleRepository; TemplateLogRepository = templateLogRepository; TemplateRepository = templateRepository; + TranslateRepository = translateRepository; UserGroupRepository = userGroupRepository; UserMenuRepository = userMenuRepository; UserRepository = userRepository; + WxAccountRepository = wxAccountRepository; + WxChatRepository = wxChatRepository; + WxMenuRepository = wxMenuRepository; + WxReplyKeywordRepository = wxReplyKeywordRepository; + WxReplyMessageRepository = wxReplyMessageRepository; + WxReplyRuleRepository = wxReplyRuleRepository; + WxUserRepository = wxUserRepository; } public List GetAllRepositories() @@ -94,8 +118,8 @@ public List GetAllRepositories() AccessTokenRepository, AdministratorRepository, AdministratorsInRolesRepository, - ChannelGroupRepository, ChannelRepository, + ChannelGroupRepository, ConfigRepository, ContentCheckRepository, ContentGroupRepository, @@ -103,12 +127,15 @@ public List GetAllRepositories() ContentTagRepository, DbCacheRepository, ErrorLogRepository, - LibraryFileRepository, - LibraryGroupRepository, - LibraryImageRepository, - LibraryTextRepository, - LibraryVideoRepository, LogRepository, + MaterialArticleRepository, + MaterialAudioRepository, + MaterialFileRepository, + MaterialGroupRepository, + MaterialImageRepository, + MaterialMessageRepository, + MaterialMessageItemRepository, + MaterialVideoRepository, PermissionsInRolesRepository, PluginConfigRepository, RelatedFieldItemRepository, @@ -118,12 +145,21 @@ public List GetAllRepositories() SitePermissionsRepository, SiteRepository, SpecialRepository, + StatRepository, TableStyleRepository, TemplateLogRepository, TemplateRepository, + TranslateRepository, UserGroupRepository, UserMenuRepository, - UserRepository + UserRepository, + WxAccountRepository, + WxChatRepository, + WxMenuRepository, + WxReplyKeywordRepository, + WxReplyMessageRepository, + WxReplyRuleRepository, + WxUserRepository }; return list; @@ -252,7 +288,7 @@ public IEnumerable> GetRows(string connectionString, public int GetPageTotalCount(string sqlString) { - var temp = sqlString.ToLower(); + var temp = StringUtils.ToLower(sqlString); var pos = temp.LastIndexOf("order by", StringComparison.Ordinal); if (pos > -1) sqlString = sqlString.Substring(0, pos); @@ -268,7 +304,7 @@ public string GetStlPageSqlString(string sqlString, string orderString, int tota { var retVal = string.Empty; - var temp = sqlString.ToLower(); + var temp = StringUtils.ToLower(sqlString); var pos = temp.LastIndexOf("order by", StringComparison.Ordinal); if (pos > -1) sqlString = sqlString.Substring(0, pos); @@ -346,15 +382,10 @@ public string GetStlPageSqlString(string sqlString, string orderString, int tota public string GetSelectSqlString(string tableName, int totalNum, string columns, string whereString, string orderByString) { - return GetSelectSqlString(_settingsManager.Database.ConnectionString, tableName, totalNum, columns, whereString, orderByString); - } - - private string GetSelectSqlString(string connectionString, string tableName, int totalNum, string columns, string whereString, string orderByString) - { - return GetSelectSqlString(connectionString, tableName, totalNum, columns, whereString, orderByString, string.Empty); + return GetSelectSqlString(tableName, totalNum, columns, whereString, orderByString, string.Empty); } - private string GetSelectSqlString(string connectionString, string tableName, int totalNum, string columns, string whereString, string orderByString, string joinString) + private string GetSelectSqlString(string tableName, int totalNum, string columns, string whereString, string orderByString, string joinString) { if (!string.IsNullOrEmpty(whereString)) { diff --git a/src/SSCMS.Core/Services/OldPluginManager.Config.cs b/src/SSCMS.Core/Services/OldPluginManager.Config.cs deleted file mode 100644 index 4386156f1..000000000 --- a/src/SSCMS.Core/Services/OldPluginManager.Config.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Threading.Tasks; -using Newtonsoft.Json; -using SSCMS.Models; - -namespace SSCMS.Core.Services -{ - public partial class OldPluginManager - { - public async Task SetConfigAsync(string pluginId, int siteId, object config) - { - return await SetConfigAsync(pluginId, siteId, string.Empty, config); - } - - public async Task SetConfigAsync(string pluginId, int siteId, string name, object config) - { - if (name == null) name = string.Empty; - - try - { - if (config == null) - { - await _pluginConfigRepository.DeleteAsync(pluginId, siteId, name); - } - else - { - var settings = new JsonSerializerSettings - { - NullValueHandling = NullValueHandling.Ignore - }; - var json = JsonConvert.SerializeObject(config, Formatting.Indented, settings); - if (await _pluginConfigRepository.IsExistsAsync(pluginId, siteId, name)) - { - var pluginConfig = new PluginConfig - { - PluginId = pluginId, - SiteId = siteId, - ConfigName = name, - ConfigValue = json - }; - await _pluginConfigRepository.UpdateAsync(pluginConfig); - } - else - { - var pluginConfig = new PluginConfig - { - PluginId = pluginId, - SiteId = siteId, - ConfigName = name, - ConfigValue = json - }; - await _pluginConfigRepository.InsertAsync(pluginConfig); - } - } - } - catch (Exception ex) - { - await _errorLogRepository.AddErrorLogAsync(pluginId, ex); - return false; - } - return true; - } - - public async Task GetConfigAsync(string pluginId, int siteId, string name = "") - { - if (name == null) name = string.Empty; - - try - { - var value = await _pluginConfigRepository.GetValueAsync(pluginId, siteId, name); - if (!string.IsNullOrEmpty(value)) - { - return JsonConvert.DeserializeObject(value); - } - } - catch (Exception ex) - { - await _errorLogRepository.AddErrorLogAsync(pluginId, ex); - } - return default(T); - } - - public async Task RemoveConfigAsync(string pluginId, int siteId, string name = "") - { - if (name == null) name = string.Empty; - - try - { - await _pluginConfigRepository.DeleteAsync(pluginId, siteId, name); - } - catch (Exception ex) - { - await _errorLogRepository.AddErrorLogAsync(pluginId, ex); - return false; - } - return true; - } - } -} diff --git a/src/SSCMS.Core/Services/OldPluginManager.Job.cs b/src/SSCMS.Core/Services/OldPluginManager.Job.cs deleted file mode 100644 index 3c8e0426f..000000000 --- a/src/SSCMS.Core/Services/OldPluginManager.Job.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace SSCMS.Core.Services -{ - public partial class OldPluginManager - { - public Dictionary> GetJobs() - { - var jobs = new Dictionary>(StringComparer.CurrentCultureIgnoreCase); - - foreach (var plugin in GetPlugins()) - { - if (plugin.Jobs != null && plugin.Jobs.Count > 0) - { - foreach (var command in plugin.Jobs.Keys) - { - jobs[command] = plugin.Jobs[command]; - } - } - } - - return jobs; - } - } -} diff --git a/src/SSCMS.Core/Services/OldPluginManager.Menu.cs b/src/SSCMS.Core/Services/OldPluginManager.Menu.cs deleted file mode 100644 index 1e26e3093..000000000 --- a/src/SSCMS.Core/Services/OldPluginManager.Menu.cs +++ /dev/null @@ -1,332 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Threading.Tasks; -using SSCMS.Configuration; -using SSCMS.Models; -using SSCMS.Utils; - -namespace SSCMS.Core.Services -{ - public partial class OldPluginManager - { - public async Task GetSystemDefaultPageUrlAsync(int siteId) - { - string pageUrl = null; - - foreach (var plugin in GetPlugins()) - { - if (plugin.SystemDefaultPageUrl == null) continue; - - try - { - pageUrl = GetMenuHref(plugin.PluginId, plugin.SystemDefaultPageUrl, siteId, 0, 0); - } - catch (Exception ex) - { - await _databaseManager.ErrorLogRepository.AddErrorLogAsync(plugin.PluginId, ex); - } - } - - return pageUrl; - } - - public async Task GetHomeDefaultPageUrlAsync() - { - string pageUrl = null; - - foreach (var plugin in GetPlugins()) - { - if (plugin.HomeDefaultPageUrl == null) continue; - - try - { - pageUrl = GetMenuHref(plugin.PluginId, plugin.HomeDefaultPageUrl, 0, 0, 0); - } - catch (Exception ex) - { - await _databaseManager.ErrorLogRepository.AddErrorLogAsync(plugin.PluginId, ex); - } - } - - return pageUrl; - } - - public async Task> GetTopMenusAsync() - { - var menus = new List(); - - var plugins = GetPlugins(); - - foreach (var plugin in plugins) - { - try - { - var systemMenus = plugin.GetSystemMenus() ?? await plugin.GetSystemMenusAsync(); - if (systemMenus == null) continue; - - var i = 0; - foreach (var systemMenu in systemMenus) - { - var pluginMenu = GetMenu(plugin.PluginId, 0, 0, 0, systemMenu, ++i); - menus.Add(pluginMenu); - } - } - catch (Exception ex) - { - await _databaseManager.ErrorLogRepository.AddErrorLogAsync(plugin.PluginId, ex); - } - } - - return menus; - } - - public async Task> GetSiteMenusAsync(int siteId) - { - var menus = new List(); - - var plugins = GetPlugins(); - - foreach (var plugin in plugins) - { - try - { - var siteMenus = plugin.GetSiteMenus(siteId) ?? await plugin.GetSiteMenusAsync(siteId); - if (siteMenus == null) continue; - - var i = 0; - foreach (var siteMenu in siteMenus) - { - var pluginMenu = GetMenu(plugin.PluginId, siteId, 0, 0, siteMenu, ++i); - menus.Add(pluginMenu); - } - } - catch (Exception ex) - { - await _databaseManager.ErrorLogRepository.AddErrorLogAsync(plugin.PluginId, ex); - } - } - - return menus; - } - - public async Task> GetContentMenusAsync(List pluginIds, Content content) - { - var menus = new List(); - if (pluginIds == null || pluginIds.Count == 0) return menus; - - foreach (var plugin in GetPlugins()) - { - if (!pluginIds.Contains(plugin.PluginId)) continue; - - try - { - var contentMenus = plugin.GetContentMenus(content) ?? await plugin.GetContentMenusAsync(content); - if (contentMenus == null) continue; - - var i = 0; - foreach (var contentMenu in contentMenus) - { - var pluginMenu = GetMenu(plugin.PluginId, content.SiteId, content.ChannelId, content.Id, contentMenu, ++i); - menus.Add(pluginMenu); - } - } - catch (Exception ex) - { - await _databaseManager.ErrorLogRepository.AddErrorLogAsync(plugin.PluginId, ex); - } - } - - return menus; - } - - private string GetMenuHref(string pluginId, string href, int siteId, int channelId, int contentId) - { - if (PageUtils.IsAbsoluteUrl(href)) - { - return href; - } - - var url = PageUtils.AddQueryStringIfNotExists(_pathManager.ParsePluginUrl(pluginId, href), new NameValueCollection - { - {"v", StringUtils.GetRandomInt(1, 1000).ToString()}, - {"pluginId", pluginId}, - {"apiUrl", _pathManager.InnerApiUrl} - }); - if (siteId > 0) - { - url = PageUtils.AddQueryStringIfNotExists(url, new NameValueCollection - { - {"siteId", siteId.ToString()} - }); - } - if (channelId > 0) - { - url = PageUtils.AddQueryStringIfNotExists(url, new NameValueCollection - { - {"channelId", channelId.ToString()} - }); - } - if (contentId > 0) - { - url = PageUtils.AddQueryStringIfNotExists(url, new NameValueCollection - { - {"contentId", contentId.ToString()} - }); - } - return url; - } - - private Menu GetMenu(string pluginId, int siteId, int channelId, int contentId, Menu metadataMenu, int i) - { - var menu = new Menu - { - Id = metadataMenu.Id, - Text = metadataMenu.Text, - Link = metadataMenu.Link, - Target = metadataMenu.Target, - IconClass = metadataMenu.IconClass - }; - - if (string.IsNullOrEmpty(menu.Id)) - { - menu.Id = pluginId + i; - } - if (!string.IsNullOrEmpty(menu.Link)) - { - menu.Link = GetMenuHref(pluginId, menu.Link, siteId, channelId, contentId); - } - if (channelId == 0 && contentId == 0 && string.IsNullOrEmpty(menu.Target)) - { - menu.Target = "right"; - } - - if (metadataMenu.Children != null && metadataMenu.Children.Count > 0) - { - var children = new List(); - var x = 1; - foreach (var childMetadataMenu in metadataMenu.Children) - { - var child = GetMenu(pluginId, siteId, channelId, contentId, childMetadataMenu, x++); - - children.Add(child); - } - menu.Children = children; - } - - return menu; - } - - public Menu GetPluginTab(string pluginId, string prefix, Menu menu) - { - var tab = new Menu - { - Id = menu.Id, - Text = menu.Text, - IconClass = menu.IconClass, - Link = menu.Link, - Target = menu.Target - }; - - var permissions = new List(); - if (menu.Children != null && menu.Children.Count > 0) - { - tab.Children = new List(); - for (var i = 0; i < menu.Children.Count; i++) - { - var child = menu.Children[i]; - var childPermission = GetMenuPermission(pluginId, menu.Text, child); - permissions.Add(childPermission); - - tab.Children[i] = GetPluginTab(pluginId, menu.Text, child); - } - } - else - { - var permission = GetMenuPermission(pluginId, prefix, menu); - permissions.Add(permission); - } - tab.Permissions = permissions; - - return tab; - } - - public async Task> GetTopPermissionsAsync() - { - var permissions = new List(); - - foreach (var plugin in GetPlugins()) - { - try - { - var systemMenus = plugin.GetSystemMenus() ?? await plugin.GetSystemMenusAsync(); - if (systemMenus == null) continue; - - permissions.Add(new Permission - { - Id = plugin.PluginId, - Text = $"系统管理 -> {plugin.Name}(插件)" - }); - } - catch (Exception ex) - { - await _errorLogRepository.AddErrorLogAsync(plugin.PluginId, ex); - } - } - - return permissions; - } - - private string GetMenuPermission(string pluginId, string prefix, Menu menu) - { - return string.IsNullOrEmpty(prefix) ? $"{pluginId}:{menu.Text}" : $"{pluginId}:{prefix}:{menu.Text}"; - } - - public async Task> GetSitePermissionsAsync(int siteId) - { - var permissions = new List(); - - foreach (var plugin in GetPlugins()) - { - try - { - var siteMenus = plugin.GetSiteMenus(siteId) ?? await plugin.GetSiteMenusAsync(siteId); - if (siteMenus == null) continue; - - foreach (var siteMenu in siteMenus) - { - if (siteMenu == null) continue; - - if (siteMenu.Children != null && siteMenu.Children.Count > 0) - { - foreach (var menu in siteMenu.Children) - { - var permission = GetMenuPermission(plugin.PluginId, siteMenu.Text, menu); - permissions.Add(new Permission - { - Id = permission, - Text = $"{plugin.Name} -> {menu.Text}" - }); - } - } - else - { - var permission = GetMenuPermission(plugin.PluginId, string.Empty, siteMenu); - permissions.Add(new Permission - { - Id = permission, - Text = $"{plugin.Name} -> {siteMenu.Text}" - }); - } - } - } - catch (Exception ex) - { - await _errorLogRepository.AddErrorLogAsync(plugin.PluginId, ex); - } - } - - return permissions; - } - } -} diff --git a/src/SSCMS.Core/Services/OldPluginManager.Package.cs b/src/SSCMS.Core/Services/OldPluginManager.Package.cs deleted file mode 100644 index d69ce856b..000000000 --- a/src/SSCMS.Core/Services/OldPluginManager.Package.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using SSCMS.Core.Plugins; -using SSCMS.Enums; -using SSCMS.Utils; - -namespace SSCMS.Core.Services -{ - public partial class OldPluginManager - { - public bool UpdatePackage(string idWithVersion, PackageType packageType, out string errorMessage) - { - try - { - var packagePath = _pathManager.GetPackagesPath(idWithVersion); - - string nuspecPath; - string dllDirectoryPath; - var metadata = PackageMetadata.GetPackageMetadataFromPackages(_pathManager, idWithVersion, out nuspecPath, out dllDirectoryPath, out errorMessage); - if (metadata == null) - { - return false; - } - - if (packageType == PackageType.SsCms) - { - var packageWebConfigPath = PathUtils.Combine(packagePath, Constants.ConfigFileName); - if (!FileUtils.IsFileExists(packageWebConfigPath)) - { - errorMessage = $"升级包 {Constants.ConfigFileName} 文件不存在"; - return false; - } - - //DirectoryUtils.Copy(PathUtils.Combine(packagePath, DirectoryUtils.SiteFiles.DirectoryName), - // PathUtils.GetSiteFilesPath(string.Empty), true); - //DirectoryUtils.Copy(PathUtils.Combine(packagePath, DirectoryUtils.SiteServer.DirectoryName), - // PathUtils.GetAdminDirectoryPath(string.Empty), true); - //DirectoryUtils.Copy(PathUtils.Combine(packagePath, DirectoryUtils.Bin.DirectoryName), - // PathUtils.GetBinDirectoryPath(string.Empty), true); - //FileUtils.CopyFile(packageWebConfigPath, - // PathUtils.Combine(WebConfigUtils.PhysicalApplicationPath, WebConfigUtils.WebConfigFileName), - // true); - } - else if (packageType == PackageType.Plugin) - { - var pluginPath = _pathManager.GetPluginPath(metadata.PluginId); - DirectoryUtils.CreateDirectoryIfNotExists(pluginPath); - - DirectoryUtils.Copy(PathUtils.Combine(packagePath, "content"), pluginPath, true); - DirectoryUtils.Copy(dllDirectoryPath, PathUtils.Combine(pluginPath, "Bin"), true); - - //var dependencyPackageDict = GetDependencyPackages(metadata); - //foreach (var dependencyPackageId in dependencyPackageDict.Keys) - //{ - // var dependencyPackageVersion = dependencyPackageDict[dependencyPackageId]; - // var dependencyDdlDirectoryPath = - // FindDllDirectoryPath( - // PathUtils.GetPackagesPath($"{dependencyPackageId}.{dependencyPackageVersion}")); - // DirectoryUtils.Copy(dependencyDdlDirectoryPath, PathUtils.Combine(pluginPath, "Bin"), true); - //} - - var configFilelPath = PathUtils.Combine(pluginPath, $"{metadata.PluginId}.nuspec"); - FileUtils.CopyFile(nuspecPath, configFilelPath, true); - } - else if (packageType == PackageType.Library) - { - var fileNames = DirectoryUtils.GetFileNames(dllDirectoryPath); - foreach (var fileName in fileNames) - { - if (StringUtils.EndsWithIgnoreCase(fileName, ".dll")) - { - var sourceDllPath = PathUtils.Combine(dllDirectoryPath, fileName); - var destDllPath = _pathManager.GetBinDirectoryPath(fileName); - if (!FileUtils.IsFileExists(destDllPath)) - { - FileUtils.CopyFile(sourceDllPath, destDllPath, false); - } - } - } - - } - } - catch (Exception ex) - { - errorMessage = ex.Message; - return false; - } - - return true; - } - } -} diff --git a/src/SSCMS.Core/Services/OldPluginManager.StlParser.cs b/src/SSCMS.Core/Services/OldPluginManager.StlParser.cs deleted file mode 100644 index 4e2cfa89c..000000000 --- a/src/SSCMS.Core/Services/OldPluginManager.StlParser.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace SSCMS.Core.Services -{ - public partial class OldPluginManager - { - public Dictionary> GetParses() - { - var elementsToParse = new Dictionary>(); - - foreach (var plugin in GetPlugins()) - { - if (plugin.StlElementsToParse != null && plugin.StlElementsToParse.Count > 0) - { - foreach (var elementName in plugin.StlElementsToParse.Keys) - { - elementsToParse[elementName.ToLower()] = plugin.StlElementsToParse[elementName]; - } - } - } - - return elementsToParse; - } - } -} diff --git a/src/SSCMS.Core/Services/OldPluginManager.Tables.cs b/src/SSCMS.Core/Services/OldPluginManager.Tables.cs deleted file mode 100644 index 89012916d..000000000 --- a/src/SSCMS.Core/Services/OldPluginManager.Tables.cs +++ /dev/null @@ -1,346 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using SSCMS.Configuration; -using SSCMS.Core.Utils; -using SSCMS.Models; -using SSCMS.Utils; -using TableColumn = Datory.TableColumn; - -namespace SSCMS.Core.Services -{ - public partial class OldPluginManager - { - public async void SyncTable(IOldPlugin pluginService) - { - if (pluginService.DatabaseTables == null || pluginService.DatabaseTables.Count <= 0) return; - - foreach (var tableName in pluginService.DatabaseTables.Keys) - { - var tableColumns = pluginService.DatabaseTables[tableName]; - if (tableColumns == null || tableColumns.Count == 0) continue; - - if (!await _settingsManager.Database.IsTableExistsAsync(tableName)) - { - await _settingsManager.Database.CreateTableAsync(tableName, tableColumns); - } - else - { - await _settingsManager.Database.AlterTableAsync(tableName, tableColumns); - } - } - } - - public bool IsContentTable(IOldPlugin pluginService) - { - return !string.IsNullOrEmpty(pluginService.ContentTableName) && - pluginService.ContentTableColumns != null && pluginService.ContentTableColumns.Count > 0; - } - - public string GetTableName(string pluginId) - { - foreach (var plugin in GetPlugins()) - { - if (plugin.PluginId == pluginId && IsContentTable(plugin)) - { - return plugin.ContentTableName; - } - } - - return string.Empty; - } - - public async Task SyncContentTableAsync(IOldPlugin pluginService) - { - if (!IsContentTable(pluginService)) return; - - var tableName = pluginService.ContentTableName; - - var tableColumns = new List(); - tableColumns.AddRange(_databaseManager.ContentRepository.GetTableColumns(tableName)); - tableColumns.AddRange(pluginService.ContentTableColumns); - - var database = _settingsManager.Database; - - if (!await database.IsTableExistsAsync(tableName)) - { - await _databaseManager.ContentRepository.CreateContentTableAsync(tableName, tableColumns); - } - else - { - await database.AlterTableAsync(tableName, tableColumns, ColumnsManager.DropAttributes.Value); - } - - await ContentTableCreateOrUpdateStylesAsync(tableName, pluginService.ContentInputStyles); - } - - private async Task ContentTableCreateOrUpdateStylesAsync(string tableName, List inputStyles) - { - var styleInfoList = new List(); - var columnTaxis = 0; - if (inputStyles != null) - { - foreach (var inputStyle in inputStyles) - { - columnTaxis++; - var styleInfo = await _databaseManager.TableStyleRepository.GetTableStyleAsync(tableName, inputStyle.AttributeName, _databaseManager.TableStyleRepository.EmptyRelatedIdentities); - - var isEquals = true; - - if (styleInfo.InputType != inputStyle.InputType) - { - isEquals = false; - styleInfo.InputType = inputStyle.InputType; - } - - if (!StringUtils.EqualsIgnoreNull(styleInfo.DisplayName, inputStyle.DisplayName)) - { - isEquals = false; - styleInfo.DisplayName = inputStyle.DisplayName; - } - - if (!StringUtils.EqualsIgnoreNull(styleInfo.HelpText, inputStyle.HelpText)) - { - isEquals = false; - styleInfo.HelpText = inputStyle.HelpText; - } - - if (!StringUtils.EqualsIgnoreNull(styleInfo.DefaultValue, inputStyle.DefaultValue)) - { - isEquals = false; - styleInfo.DefaultValue = inputStyle.DefaultValue; - } - - if (styleInfo.Taxis != columnTaxis) - { - isEquals = false; - styleInfo.Taxis = columnTaxis; - } - - //if (styleInfo.IsRequired != inputStyle.IsRequired) - //{ - // isEquals = false; - // styleInfo.IsRequired = inputStyle.IsRequired; - //} - - //if (styleInfo.ValidateType != inputStyle.ValidateType) - //{ - // isEquals = false; - // styleInfo.ValidateType = inputStyle.ValidateType; - //} - - //if (styleInfo.MinNum != inputStyle.MinNum) - //{ - // isEquals = false; - // styleInfo.MinNum = inputStyle.MinNum; - //} - - //if (styleInfo.MaxNum != inputStyle.MaxNum) - //{ - // isEquals = false; - // styleInfo.MaxNum = inputStyle.MaxNum; - //} - - //if (!StringUtils.EqualsIgnoreNull(styleInfo.RegExp, inputStyle.RegExp)) - //{ - // isEquals = false; - // styleInfo.RegExp = inputStyle.RegExp; - //} - - if (!StringUtils.EqualsIgnoreNull(styleInfo.Width, inputStyle.Width)) - { - isEquals = false; - styleInfo.Width = inputStyle.Width; - } - - if (!(styleInfo.Height == 0 && string.IsNullOrEmpty(inputStyle.Height)) && styleInfo.Height != TranslateUtils.ToInt(inputStyle.Height)) - { - isEquals = false; - styleInfo.Height = TranslateUtils.ToInt(inputStyle.Height); - } - - if (!(styleInfo.Items == null && inputStyle.Items == null)) - { - var styleItems = styleInfo.Items ?? new List(); - var listItems = inputStyle.Items ?? new List(); - - if (styleItems.Count > listItems.Count) - { - isEquals = false; - styleItems.RemoveRange(listItems.Count, styleItems.Count - listItems.Count); - } - - for (var i = 0; i < listItems.Count; i++) - { - var listItem = listItems[i]; - if (styleItems.Count < i + 1) - { - isEquals = false; - styleItems.Add(new InputStyleItem - { - Label = listItem.Label, - Value = listItem.Value, - Selected = listItem.Selected - }); - } - else - { - var styleItem = styleItems[i]; - - if (!StringUtils.EqualsIgnoreNull(styleItem.Label, listItem.Label)) - { - isEquals = false; - styleItem.Label = listItem.Label; - } - - if (!StringUtils.EqualsIgnoreNull(styleItem.Value, listItem.Value)) - { - isEquals = false; - styleItem.Value = listItem.Value; - } - - if (styleItem.Selected != listItem.Selected) - { - isEquals = false; - styleItem.Selected = listItem.Selected; - } - } - } - } - - if (isEquals) continue; - - styleInfo.List = false; - styleInfoList.Add(styleInfo); - } - } - - foreach (var styleInfo in styleInfoList) - { - if (styleInfo.Id == 0) - { - await _databaseManager.TableStyleRepository.InsertAsync(_databaseManager.TableStyleRepository.EmptyRelatedIdentities, styleInfo); - } - else - { - await _databaseManager.TableStyleRepository.UpdateAsync(styleInfo); - } - } - } - - public List GetContentModelPlugins() - { - var list = new List(); - - foreach (var plugin in GetPlugins()) - { - if (IsContentTable(plugin)) - { - list.Add(plugin); - } - } - - return list; - } - - public List GetContentTableNameList() - { - var list = new List(); - - foreach (var plugin in GetPlugins()) - { - if (IsContentTable(plugin)) - { - if (!ListUtils.ContainsIgnoreCase(list, plugin.ContentTableName)) - { - list.Add(plugin.ContentTableName); - } - } - } - - return list; - } - - public List GetAllContentRelatedPlugins(bool includeContentTable) - { - var list = new List(); - - foreach (var plugin in GetPlugins()) - { - var isContentModel = IsContentTable(plugin); - - if (!includeContentTable && isContentModel) continue; - - if (isContentModel) - { - list.Add(plugin); - } - else if (plugin.ContentColumns != null && plugin.ContentColumns.Count > 0) - { - list.Add(plugin); - } - //else - //{ - // var contentMenus = plugin.GetContentMenus(content) ?? await plugin.GetContentMenusAsync(content); - // if (contentMenus == null) continue; - //} - } - - return list; - } - - public List GetContentPlugins(Channel channel, bool includeContentTable) - { - var list = new List(); - var pluginIds = ListUtils.GetStringList(channel.ContentRelatedPluginIds); - if (!string.IsNullOrEmpty(channel.ContentModelPluginId)) - { - pluginIds.Add(channel.ContentModelPluginId); - } - - foreach (var plugin in GetPlugins()) - { - if (!pluginIds.Contains(plugin.PluginId)) continue; - - if (!includeContentTable && IsContentTable(plugin)) continue; - - list.Add(plugin); - } - - return list; - } - - public List GetContentPluginIds(Channel channel) - { - if (channel.ContentRelatedPluginIds != null && channel.ContentRelatedPluginIds.Any() && - string.IsNullOrEmpty(channel.ContentModelPluginId)) - { - return null; - } - - var pluginIds = ListUtils.GetStringList(channel.ContentRelatedPluginIds); - if (!string.IsNullOrEmpty(channel.ContentModelPluginId)) - { - pluginIds.Add(channel.ContentModelPluginId); - } - - return pluginIds; - } - - public Dictionary>> GetContentColumns(List pluginIds) - { - var dict = new Dictionary>>(); - if (pluginIds == null || pluginIds.Count == 0) return dict; - - foreach (var plugin in GetPlugins()) - { - if (!pluginIds.Contains(plugin.PluginId) || plugin.ContentColumns == null || plugin.ContentColumns.Count == 0) continue; - - dict[plugin.PluginId] = plugin.ContentColumns; - } - - return dict; - } - } -} diff --git a/src/SSCMS.Core/Services/OldPluginManager.cs b/src/SSCMS.Core/Services/OldPluginManager.cs deleted file mode 100644 index 53416b064..000000000 --- a/src/SSCMS.Core/Services/OldPluginManager.cs +++ /dev/null @@ -1,365 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.Extensions.DependencyInjection; -using SSCMS.Repositories; -using SSCMS.Services; -using SSCMS.Utils; - -namespace SSCMS.Core.Services -{ - public partial class OldPluginManager : IOldPluginManager - { - private readonly IServiceProvider _serviceProvider; - private readonly ISettingsManager _settingsManager; - private readonly IPathManager _pathManager; - private readonly IDatabaseManager _databaseManager; - private readonly IPluginConfigRepository _pluginConfigRepository; - private readonly IErrorLogRepository _errorLogRepository; - - public OldPluginManager(IServiceProvider serviceProvider, ISettingsManager settingsManager, IPathManager pathManager, IDatabaseManager databaseManager, IPluginConfigRepository pluginConfigRepository, IErrorLogRepository errorLogRepository) - { - _serviceProvider = serviceProvider; - _settingsManager = settingsManager; - _pathManager = pathManager; - _databaseManager = databaseManager; - _pluginConfigRepository = pluginConfigRepository; - _errorLogRepository = errorLogRepository; - } - - public List GetPlugins() - { - var list = _serviceProvider.GetServices(); - return list.ToList(); - } - - public bool IsExists(string pluginId) - { - if (string.IsNullOrEmpty(pluginId)) return false; - - var plugins = GetPlugins(); - return plugins.Exists(x => StringUtils.EqualsIgnoreCase(x.PluginId, pluginId)); - } - - public IOldPlugin GetPlugin(string pluginId) - { - if (string.IsNullOrEmpty(pluginId)) return null; - - var plugins = GetPlugins(); - return plugins.FirstOrDefault(x => StringUtils.EqualsIgnoreCase(x.PluginId, pluginId)); - } - - public List PackagesIdAndVersionList - { - get - { - var packagesPath = _pathManager.GetPackagesPath(); - DirectoryUtils.CreateDirectoryIfNotExists(packagesPath); - return DirectoryUtils.GetDirectoryNames(packagesPath).ToList(); - } - } - - - - //public List GetAllContentModels(SiteInfo siteInfo) - //{ - // var cacheName = nameof(GetAllContentModels) + siteInfo.Id; - // var contentModels = GetCache>(cacheName); - // if (contentModels != null) return contentModels; - - // contentModels = new List(); - - // foreach (var pluginInfo in GetEnabledPluginInfoLists()) - // { - // var model = pluginInfo.Plugin as IContentModel; - - // if (model == null) continue; - - // var tableName = siteInfo.AuxiliaryTableForContent; - // var tableType = EAuxiliaryTableType.BackgroundContent; - // if (model.ContentTableColumns != null && model.ContentTableColumns.Count > 0) - // { - // tableName = pluginInfo.Id; - // tableType = EAuxiliaryTableType.Custom; - // } - - // contentModels.Add(new ContentModelInfo( - // pluginInfo.Id, - // pluginInfo.Id, - // $"插件:{pluginInfo.Metadata.DisplayName}", - // tableName, - // tableType, - // PageUtils.GetPluginDirectoryUrl(pluginInfo.Id, pluginInfo.Metadata.Icon)) - // ); - // } - - // SetCache(cacheName, contentModels); - - // return contentModels; - //} - - - - //public List GetAllContentModels(SiteInfo siteInfo) - //{ - // var cacheName = nameof(GetAllContentModels) + siteInfo.Id; - // var contentModels = GetCache>(cacheName); - // if (contentModels != null) return contentModels; - - // contentModels = new List(); - - // foreach (var pluginInfo in GetEnabledPluginInfoLists()) - // { - // var model = pluginInfo.Plugin as IContentModel; - - // if (model == null) continue; - - // var links = new List(); - // if (model.ContentLinks != null) - // { - // links.AddRange(model.ContentLinks.Select(link => new PluginContentLink - // { - // Text = link.Text, - // Href = PageUtils.GetPluginDirectoryUrl(pluginInfo.Id, link.Href), - // Target = link.Target - // })); - // } - // var tableName = siteInfo.AuxiliaryTableForContent; - // var tableType = EAuxiliaryTableType.BackgroundContent; - // if (model.IsCustomContentTable && model.CustomContentTableColumns != null && model.CustomContentTableColumns.Count > 0) - // { - // tableName = pluginInfo.Id; - // tableType = EAuxiliaryTableType.Custom; - // } - - // contentModels.Add(new ContentModelInfo( - // pluginInfo.Id, - // pluginInfo.Id, - // $"插件:{pluginInfo.Metadata.DisplayName}", - // tableName, - // tableType, - // PageUtils.GetPluginDirectoryUrl(pluginInfo.Id, pluginInfo.Metadata.Icon), - // links) - // ); - // } - - // SetCache(cacheName, contentModels); - - // return contentModels; - //} - - - - //public Dictionary> GetRenders() - //{ - // var renders = new Dictionary>(); - - // var pluginInfoList = GetEnabledPluginInfoList(); - // if (pluginInfoList != null && pluginInfoList.Count > 0) - // { - // foreach (var pluginInfo in pluginInfoList) - // { - // var plugin = pluginInfo.Plugin as IRender; - // if (plugin?.Render != null) - // { - // renders.Add(pluginInfo.Metadata.Id, plugin.Render); - // } - // //if (!(pluginInfo.Plugin is IRender plugin)) continue; - - // //if (plugin.Render != null) - // //{ - // // renders.Add(pluginInfo.Metadata.Id, plugin.Render); - // //} - // } - // } - - // return renders; - //} - - //public List> GetFileSystemChangedActions() - //{ - // var actions = new List>(); - - // var plugins = GetEnabledFeatures(); - // if (plugins != null && plugins.Count > 0) - // { - // foreach (var plugin in plugins) - // { - // if (plugin.FileSystemChanged != null) - // { - // actions.Add(plugin.FileSystemChanged); - // } - // } - // } - - // return actions; - //} - - - - //public bool Install(string pluginId, string version, out string errorMessage) - //{ - // errorMessage = string.Empty; - // if (string.IsNullOrEmpty(pluginId)) return false; - - // try - // { - // if (IsExists(pluginId)) - // { - // errorMessage = $"插件 {pluginId} 已存在"; - // return false; - // } - // var directoryPath = PathUtils.GetPluginPath(pluginId); - // DirectoryUtils.DeleteDirectoryIfExists(directoryPath); - - // var zipFilePath = PathUtility.GetTemporaryFilesPath(pluginId + ".zip"); - // FileUtils.DeleteFileIfExists(zipFilePath); - - // var downloadUrl = $"http://download.siteserver.cn/plugins/{pluginId}/{version}/{pluginId}.zip"; - // WebClientUtils.SaveRemoteFileToLocal(downloadUrl, zipFilePath); - - // ZipUtils.UnpackFiles(zipFilePath, directoryPath); - // FileUtils.DeleteFileIfExists(zipFilePath); - - // string dllDirectoryPath; - // var metadata = GetPluginMetadata(pluginId, out dllDirectoryPath, out errorMessage); - // if (metadata == null) - // { - // return false; - // } - - // //SaveMetadataToJson(metadata); - // } - // catch (Exception ex) - // { - // errorMessage = ex.Message; - // return false; - // } - - // return true; - //} - - public void Delete(string pluginId) - { - DirectoryUtils.DeleteDirectoryIfExists(_pathManager.GetPluginPath(pluginId)); - } - - //public async Task UpdateDisabledAsync(string pluginId, bool isDisabled) - //{ - // var plugin = GetPlugin(pluginId); - // if (plugin != null) - // { - // //pluginInfo.IsDisabled = isDisabled; - // await _databaseManager.PluginRepository.UpdateIsDisabledAsync(pluginId, isDisabled); - // } - //} - - //public async Task UpdateTaxisAsync(string pluginId, int taxis) - //{ - // var plugin = GetPlugin(pluginId); - // if (plugin != null) - // { - // //pluginInfo.Taxis = taxis; - // await _databaseManager.PluginRepository.UpdateTaxisAsync(pluginId, taxis); - // } - //} - - //public PluginMetadata UpdateDatabase(string pluginId, string databaseType, string connectionString) - //{ - // var metadata = GetMetadata(pluginId); - // if (metadata != null) - // { - // if (WebConfigUtils.IsProtectData && !string.IsNullOrEmpty(databaseType)) - // { - // databaseType = TranslateUtils.EncryptStringBySecretKey(databaseType); - // } - // if (WebConfigUtils.IsProtectData && !string.IsNullOrEmpty(connectionString)) - // { - // connectionString = TranslateUtils.EncryptStringBySecretKey(connectionString); - // } - // metadata.DatabaseType = databaseType; - // metadata.ConnectionString = connectionString; - // SaveMetadataToJson(metadata); - // } - // return metadata; - //} - - /// - /// Parse plugin metadata in giving directories - /// - /// - //internal PluginMetadata GetMetadataFromJson(string directoryPath) - //{ - // var configPath = Path.Combine(directoryPath, PluginConfigName); - // if (!File.Exists(configPath)) - // { - // return null; - // } - - // PluginMetadata metadata; - // try - // { - // metadata = JsonConvert.DeserializeObject(File.ReadAllText(configPath)); - // metadata.DirectoryPath = directoryPath; - // } - // catch - // { - // return null; - // } - - // if (string.IsNullOrEmpty(metadata.Id)) - // { - // return null; - // } - - // return metadata; - //} - - //private PackageMetadata GetPluginMetadata(string directoryName, out string dllDirectoryPath, out string errorMessage) - //{ - // dllDirectoryPath = string.Empty; - // var nuspecPath = PathUtils.GetPluginNuspecPath(directoryName); - // if (!File.Exists(nuspecPath)) - // { - // errorMessage = $"插件配置文件 {directoryName}.nuspec 不存在"; - // return null; - // } - // dllDirectoryPath = PathUtils.GetPluginDllDirectoryPath(directoryName); - // if (string.IsNullOrEmpty(dllDirectoryPath)) - // { - // errorMessage = $"插件可执行文件 {directoryName}.dll 不存在"; - // return null; - // } - - // PackageMetadata metadata; - // try - // { - // metadata = PackageUtils.GetPackageMetadata(nuspecPath); - // } - // catch(Exception ex) - // { - // errorMessage = ex.Message; - // return null; - // } - - // if (string.IsNullOrEmpty(metadata.Id)) - // { - // errorMessage = "插件配置文件不正确"; - // return null; - // } - - // errorMessage = string.Empty; - // return metadata; - //} - - public string GetPluginIconUrl(IOldPlugin pluginService) - { - var url = string.Empty; - if (pluginService.IconUrl != null) - { - url = pluginService.IconUrl.ToString(); - } - return url; - } - } -} diff --git a/src/SSCMS.Core/Services/ParseManager.StlElementParser.cs b/src/SSCMS.Core/Services/ParseManager.StlElementParser.cs index 3de2f3b97..7ad9ec40a 100644 --- a/src/SSCMS.Core/Services/ParseManager.StlElementParser.cs +++ b/src/SSCMS.Core/Services/ParseManager.StlElementParser.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading.Tasks; -using SSCMS.Core.Plugins; +using SSCMS.Core.Context; using SSCMS.Core.StlParser.StlElement; using SSCMS.Core.StlParser.Utility; +using SSCMS.Plugins; using SSCMS.Services; using SSCMS.Utils; @@ -37,49 +39,50 @@ public async Task ReplaceStlElementsAsync(StringBuilder parsedBuilder) public Dictionary>> ElementsToParseDic => new Dictionary>> { - {StlA.ElementName.ToLower(), StlA.ParseAsync}, - {StlAction.ElementName.ToLower(), StlAction.ParseAsync}, - {StlAudio.ElementName.ToLower(), StlAudio.ParseAsync}, - {StlChannel.ElementName.ToLower(), StlChannel.ParseAsync}, - {StlChannels.ElementName.ToLower(), StlChannels.ParseAsync}, - {StlContainer.ElementName.ToLower(), StlContainer.ParseAsync}, - {StlContent.ElementName.ToLower(), StlContent.ParseAsync}, - {StlContents.ElementName.ToLower(), StlContents.ParseAsync}, - {StlCount.ElementName.ToLower(), StlCount.ParseAsync}, - {StlDynamic.ElementName.ToLower(), StlDynamic.ParseAsync}, - {StlEach.ElementName.ToLower(), StlEach.ParseAsync}, - {StlFile.ElementName.ToLower(), StlFile.ParseAsync}, - {StlFlash.ElementName.ToLower(), StlFlash.ParseAsync}, - {StlFocusViewer.ElementName.ToLower(), StlFocusViewer.ParseAsync}, - {StlIf.ElementName.ToLower(), StlIf.ParseAsync}, - {StlImage.ElementName.ToLower(), StlImage.ParseAsync}, - {StlInclude.ElementName.ToLower(), StlInclude.ParseAsync}, - {StlLibrary.ElementName.ToLower(), StlLibrary.ParseAsync}, - {StlLocation.ElementName.ToLower(), StlLocation.ParseAsync}, - {StlMarquee.ElementName.ToLower(), StlMarquee.ParseAsync}, - {StlNavigation.ElementName.ToLower(), StlNavigation.ParseAsync}, - {StlPlayer.ElementName.ToLower(), StlPlayer.ParseAsync}, - {StlPrinter.ElementName.ToLower(), StlPrinter.ParseAsync}, - {StlSearch.ElementName.ToLower(), StlSearch.ParseAsync}, - {StlSearch.ElementName2.ToLower(), StlSearch.ParseAsync}, - {StlSelect.ElementName.ToLower(), StlSelect.ParseAsync}, - {StlSite.ElementName.ToLower(), StlSite.ParseAsync}, - {StlSites.ElementName.ToLower(), StlSites.ParseAsync}, - {StlSqlContent.ElementName.ToLower(), StlSqlContent.ParseAsync}, - {StlSqlContents.ElementName.ToLower(), StlSqlContents.ParseAsync}, - {StlTabs.ElementName.ToLower(), StlTabs.ParseAsync}, - {StlValue.ElementName.ToLower(), StlValue.ParseAsync}, - {StlVideo.ElementName.ToLower(), StlVideo.ParseAsync}, - {StlZoom.ElementName.ToLower(), StlZoom.ParseAsync} + {StringUtils.ToLower(StlA.ElementName), StlA.ParseAsync}, + {StringUtils.ToLower(StlAction.ElementName), StlAction.ParseAsync}, + {StringUtils.ToLower(StlAudio.ElementName), StlAudio.ParseAsync}, + {StringUtils.ToLower(StlChannel.ElementName), StlChannel.ParseAsync}, + {StringUtils.ToLower(StlChannels.ElementName), StlChannels.ParseAsync}, + {StringUtils.ToLower(StlContainer.ElementName), StlContainer.ParseAsync}, + {StringUtils.ToLower(StlContent.ElementName), StlContent.ParseAsync}, + {StringUtils.ToLower(StlContents.ElementName), StlContents.ParseAsync}, + {StringUtils.ToLower(StlCount.ElementName), StlCount.ParseAsync}, + {StringUtils.ToLower(StlDynamic.ElementName), StlDynamic.ParseAsync}, + {StringUtils.ToLower(StlEach.ElementName), StlEach.ParseAsync}, + {StringUtils.ToLower(StlFile.ElementName), StlFile.ParseAsync}, + {StringUtils.ToLower(StlFlash.ElementName), StlFlash.ParseAsync}, + {StringUtils.ToLower(StlFocusViewer.ElementName), StlFocusViewer.ParseAsync}, + {StringUtils.ToLower(StlIf.ElementName), StlIf.ParseAsync}, + {StringUtils.ToLower(StlImage.ElementName), StlImage.ParseAsync}, + {StringUtils.ToLower(StlInclude.ElementName), StlInclude.ParseAsync}, + {StringUtils.ToLower(StlMaterial.ElementName), StlMaterial.ParseAsync}, + {StringUtils.ToLower(StlLocation.ElementName), StlLocation.ParseAsync}, + {StringUtils.ToLower(StlMarquee.ElementName), StlMarquee.ParseAsync}, + {StringUtils.ToLower(StlNavigation.ElementName), StlNavigation.ParseAsync}, + {StringUtils.ToLower(StlPlayer.ElementName), StlPlayer.ParseAsync}, + {StringUtils.ToLower(StlPrinter.ElementName), StlPrinter.ParseAsync}, + {StringUtils.ToLower(StlSearch.ElementName), StlSearch.ParseAsync}, + {StringUtils.ToLower(StlSearch.ElementName2), StlSearch.ParseAsync}, + {StringUtils.ToLower(StlSelect.ElementName), StlSelect.ParseAsync}, + {StringUtils.ToLower(StlSite.ElementName), StlSite.ParseAsync}, + {StringUtils.ToLower(StlSites.ElementName), StlSites.ParseAsync}, + {StringUtils.ToLower(StlSqlContent.ElementName), StlSqlContent.ParseAsync}, + {StringUtils.ToLower(StlSqlContents.ElementName), StlSqlContents.ParseAsync}, + {StringUtils.ToLower(StlTabs.ElementName), StlTabs.ParseAsync}, + {StringUtils.ToLower(StlTags.ElementName), StlTags.ParseAsync}, + {StringUtils.ToLower(StlValue.ElementName), StlValue.ParseAsync}, + {StringUtils.ToLower(StlVideo.ElementName), StlVideo.ParseAsync}, + {StringUtils.ToLower(StlZoom.ElementName), StlZoom.ParseAsync} }; private Dictionary> ElementsToTranslateDic => new Dictionary> { - {StlPageContents.ElementName.ToLower(), StlEncrypt}, - {StlPageChannels.ElementName.ToLower(), StlEncrypt}, - {StlPageSqlContents.ElementName.ToLower(), StlEncrypt}, - //{StlPageInputContents.ElementName.ToLower(), StlParserManager.StlEncrypt}, - {StlPageItems.ElementName.ToLower(), StlEncrypt} + {StringUtils.ToLower(StlPageContents.ElementName), StlEncrypt}, + {StringUtils.ToLower(StlPageChannels.ElementName), StlEncrypt}, + {StringUtils.ToLower(StlPageSqlContents.ElementName), StlEncrypt}, + //{StringUtils.ToLower(StlPageInputContents.ElementName), StlParserManager.StlEncrypt}, + {StringUtils.ToLower(StlPageItems.ElementName), StlEncrypt} }; private async Task ParseStlElementAsync(string stlElement) @@ -140,8 +143,9 @@ private async Task ParseStlElementAsync(string stlElement) } else { - var parsers = OldPluginManager.GetParses(); - if (parsers.ContainsKey(elementName)) + var parsers = _pluginManager.GetExtensions(); + var parser = parsers?.FirstOrDefault(x => StringUtils.EqualsIgnoreCase(x.ElementName, elementName)); + if (parser != null) { if (stlElementInfo.IsDynamic) { @@ -151,12 +155,30 @@ private async Task ParseStlElementAsync(string stlElement) { try { - if (parsers.TryGetValue(elementName, out var func)) - { - var context = new PluginStlParseContext(); - context.Load(stlElementInfo.OuterHtml, stlElementInfo.InnerHtml, stlElementInfo.Attributes, PageInfo, ContextInfo); - parsedContent = func(context); - } + var context = new PluginParseStlContext(this, stlElementInfo.OuterHtml, stlElementInfo.InnerHtml, stlElementInfo.Attributes); + parsedContent = parser.Parse(context); + } + catch (Exception ex) + { + parsedContent = await AddStlErrorLogAsync(elementName, stlElement, ex); + } + } + } + + var parsersAsync = _pluginManager.GetExtensions(); + var parserAsync = parsersAsync?.FirstOrDefault(x => StringUtils.EqualsIgnoreCase(x.ElementName, elementName)); + if (parserAsync != null) + { + if (stlElementInfo.IsDynamic) + { + parsedContent = await StlDynamic.ParseDynamicElementAsync(stlElement, this); + } + else + { + try + { + var context = new PluginParseStlContext(this, stlElementInfo.OuterHtml, stlElementInfo.InnerHtml, stlElementInfo.Attributes); + parsedContent = await parserAsync.ParseAsync(context); } catch (Exception ex) { @@ -164,6 +186,30 @@ private async Task ParseStlElementAsync(string stlElement) } } } + //var parsers = OldPluginManager.GetParses(); + //if (parsers.ContainsKey(elementName)) + //{ + // if (stlElementInfo.IsDynamic) + // { + // parsedContent = await StlDynamic.ParseDynamicElementAsync(stlElement, this); + // } + // else + // { + // try + // { + // if (parsers.TryGetValue(elementName, out var func)) + // { + // var context = new PluginStlParseContext(); + // context.Load(stlElementInfo.OuterHtml, stlElementInfo.InnerHtml, stlElementInfo.Attributes, PageInfo, ContextInfo); + // parsedContent = func(context); + // } + // } + // catch (Exception ex) + // { + // parsedContent = await AddStlErrorLogAsync(elementName, stlElement, ex); + // } + // } + //} } } diff --git a/src/SSCMS.Core/Services/ParseManager.StlEntityParser.cs b/src/SSCMS.Core/Services/ParseManager.StlEntityParser.cs index 55ceda34c..361e6ce84 100644 --- a/src/SSCMS.Core/Services/ParseManager.StlEntityParser.cs +++ b/src/SSCMS.Core/Services/ParseManager.StlEntityParser.cs @@ -4,6 +4,7 @@ using SSCMS.Core.StlParser.StlEntity; using SSCMS.Core.StlParser.Utility; using SSCMS.Parse; +using SSCMS.Utils; namespace SSCMS.Core.Services { @@ -82,7 +83,7 @@ public StlEntityType GetEntityType(string stlEntity) var type = StlEntityType.Undefined; if (!string.IsNullOrEmpty(stlEntity)) { - stlEntity = stlEntity.Trim().ToLower(); + stlEntity = StringUtils.ToLower(stlEntity).Trim(); if (stlEntity.StartsWith("{stl.")) { diff --git a/src/SSCMS.Core/Services/ParseManager.cs b/src/SSCMS.Core/Services/ParseManager.cs index b843dbfc8..8532c3225 100644 --- a/src/SSCMS.Core/Services/ParseManager.cs +++ b/src/SSCMS.Core/Services/ParseManager.cs @@ -3,7 +3,8 @@ using System.Text; using System.Threading.Tasks; using Datory; -using SSCMS.Core.Plugins; +using SSCMS.Configuration; +using SSCMS.Core.Context; using SSCMS.Core.Utils; using SSCMS.Enums; using SSCMS.Models; @@ -19,15 +20,13 @@ public partial class ParseManager : IParseManager public ISettingsManager SettingsManager { get; } public IPathManager PathManager { get; } public IDatabaseManager DatabaseManager { get; } - public IOldPluginManager OldPluginManager { get; } private readonly IPluginManager _pluginManager; - public ParseManager(ISettingsManager settingsManager, IPathManager pathManager, IDatabaseManager databaseManager, IOldPluginManager oldPluginManager, IPluginManager pluginManager) + public ParseManager(ISettingsManager settingsManager, IPathManager pathManager, IDatabaseManager databaseManager, IPluginManager pluginManager) { SettingsManager = settingsManager; PathManager = pathManager; DatabaseManager = databaseManager; - OldPluginManager = oldPluginManager; _pluginManager = pluginManager; } @@ -43,38 +42,37 @@ public async Task InitAsync(Site site, int pageChannelId, int pageContentId, Tem public async Task ParseAsync(StringBuilder contentBuilder, string filePath, bool isDynamic) { - var context = new PluginStlParseContext(); - context.Load(string.Empty, string.Empty, null, PageInfo, ContextInfo); + var context = new PluginParseContext(this); - var beforeStlParsesAsync = _pluginManager.GetExtensions(); - if (beforeStlParsesAsync != null) + var startParsesAsync = _pluginManager.GetExtensions(); + if (startParsesAsync != null) { - foreach (var extension in beforeStlParsesAsync) + foreach (var extension in startParsesAsync) { try { - await extension.BeforeStlParseAsync(context); + await extension.ParseAsync(context); } catch (Exception ex) { - await AddStlErrorLogAsync(nameof(IPluginBeforeStlParseAsync), string.Empty, + await AddStlErrorLogAsync(nameof(IPluginCreateStartAsync), string.Empty, ex); } } } - var beforeStlParses = _pluginManager.GetExtensions(); - if (beforeStlParses != null) + var startParses = _pluginManager.GetExtensions(); + if (startParses != null) { - foreach (var extension in beforeStlParses) + foreach (var extension in startParses) { try { - extension.BeforeStlParse(context); + extension.Parse(context); } catch (Exception ex) { - await AddStlErrorLogAsync(nameof(IPluginBeforeStlParseAsync), string.Empty, + await AddStlErrorLogAsync(nameof(IPluginCreateStartAsync), string.Empty, ex); } } @@ -85,22 +83,35 @@ await AddStlErrorLogAsync(nameof(IPluginBeforeStlParseAsync), string.Empty, await ParseTemplateContentAsync(contentBuilder); } - var afterStlParses = _pluginManager.GetExtensions(); - if (afterStlParses != null) + var endParsesAsync = _pluginManager.GetExtensions(); + if (endParsesAsync != null) { - foreach (var extension in afterStlParses) + foreach (var extension in endParsesAsync) { try { - extension.AfterStlParse(context); - //plugin.OnAfterStlParse(new ParseEventArgs(PageInfo.SiteId, PageInfo.PageChannelId, - // PageInfo.PageContentId, await GetContentAsync(), - // PageInfo.Template.TemplateType, PageInfo.Template.Id, filePath, PageInfo.HeadCodes, - // PageInfo.BodyCodes, PageInfo.FootCodes, contentBuilder)); + await extension.ParseAsync(context); } catch (Exception ex) { - await AddStlErrorLogAsync(nameof(IPluginAfterStlParse), string.Empty, + await AddStlErrorLogAsync(nameof(IPluginCreateEndAsync), string.Empty, + ex); + } + } + } + + var endParses = _pluginManager.GetExtensions(); + if (endParses != null) + { + foreach (var extension in endParses) + { + try + { + extension.Parse(context); + } + catch (Exception ex) + { + await AddStlErrorLogAsync(nameof(IPluginCreateEnd), string.Empty, ex); } } @@ -111,7 +122,7 @@ await AddStlErrorLogAsync(nameof(IPluginAfterStlParse), string.Empty, if (isDynamic) { var pageUrl = PageUtils.AddProtocolToUrl( - PathManager.ParseNavigationUrl( + PathManager.ParseUrl( $"~/{PathUtils.GetPathDifference(SettingsManager.WebRootPath, filePath)}")); string templateString = $@" "; @@ -152,8 +163,7 @@ await AddStlErrorLogAsync(nameof(IPluginAfterStlParse), string.Empty, fileTemplateId = PageInfo.Template.Id; } - var apiUrl = PageInfo.ApiUrl; - var ajaxUrl = PathManager.GetTriggerApiUrl(apiUrl, PageInfo.SiteId, ContextInfo.ChannelId, + var ajaxUrl = PathManager.GetTriggerApiUrl(PageInfo.SiteId, ContextInfo.ChannelId, ContextInfo.ContentId, fileTemplateId, true); if (!PageInfo.FootCodes.ContainsKey("CreateDoubleClick")) { diff --git a/src/SSCMS.Core/Services/PathManager.Api.cs b/src/SSCMS.Core/Services/PathManager.Api.cs deleted file mode 100644 index 3e794bb5a..000000000 --- a/src/SSCMS.Core/Services/PathManager.Api.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Specialized; -using SSCMS.Core.StlParser.StlElement; -using SSCMS.Models; -using SSCMS.Utils; - -namespace SSCMS.Core.Services -{ - public partial class PathManager - { - public string GetApiUrl(string route) - { - return PageUtils.Combine(Constants.ApiPrefix, route); - } - - public string GetApiUrl(Config config) - { - return config.IsSeparatedApi ? config.SeparatedApiUrl : "/"; - } - - public string InnerApiUrl => Constants.ApiPrefix; - - public string GetInnerApiUrl(string route) - { - return PageUtils.Combine(InnerApiUrl, route); - } - - public string GetDownloadApiUrl(string apiUrl, int siteId, int channelId, int contentId, string fileUrl) - { - return PageUtils.AddQueryString(PageUtils.Combine(apiUrl, Constants.ApiStlPrefix, Constants.RouteStlActionsDownload), new NameValueCollection - { - {"siteId", siteId.ToString()}, - {"channelId", channelId.ToString()}, - {"contentId", contentId.ToString()}, - {"fileUrl", _settingsManager.Encrypt(fileUrl)} - }); - } - - public string GetDownloadApiUrl(string apiUrl, int siteId, string fileUrl) - { - return PageUtils.AddQueryString(PageUtils.Combine(apiUrl, Constants.ApiStlPrefix, Constants.RouteStlActionsDownload), new NameValueCollection - { - {"siteId", siteId.ToString()}, - {"fileUrl", _settingsManager.Encrypt(fileUrl)} - }); - } - - public string GetDownloadApiUrl(string apiUrl, string filePath) - { - return PageUtils.AddQueryString(PageUtils.Combine(apiUrl, Constants.ApiStlPrefix, Constants.RouteStlActionsDownload), new NameValueCollection - { - {"filePath", _settingsManager.Encrypt(filePath)} - }); - } - - public string GetDynamicApiUrl(string apiUrl) - { - return PageUtils.Combine(apiUrl, Constants.ApiStlPrefix, Constants.RouteStlActionsDynamic); - } - - public string GetIfApiUrl(string apiUrl) - { - return PageUtils.Combine(apiUrl, Constants.ApiStlPrefix, Constants.RouteStlRouteActionsIf); - } - - public string GetPageContentsApiUrl(string apiUrl) - { - return PageUtils.Combine(apiUrl, Constants.ApiStlPrefix, Constants.RouteStlActionsPageContents); - } - - public string GetPageContentsApiParameters(int siteId, int pageChannelId, int templateId, int totalNum, int pageCount, - int currentPageIndex, string stlPageContentsElement) - { - return $@" -{{ - siteId: {siteId}, - pageChannelId: {pageChannelId}, - templateId: {templateId}, - totalNum: {totalNum}, - pageCount: {pageCount}, - currentPageIndex: {currentPageIndex}, - stlPageContentsElement: '{_settingsManager.Encrypt(stlPageContentsElement)}' -}}"; - } - - public string GetSearchApiUrl(string apiUrl) - { - return PageUtils.Combine(apiUrl, Constants.ApiStlPrefix, Constants.RouteStlActionsSearch); - } - - public string GetSearchApiParameters(bool isAllSites, string siteName, string siteDir, string siteIds, string channelIndex, string channelName, string channelIds, string type, string word, string dateAttribute, string dateFrom, string dateTo, string since, int pageNum, bool isHighlight, int siteId, string ajaxDivId, string template) - { - return $@" -{{ - {StlSearch.IsAllSites.ToLower()}: {isAllSites.ToString().ToLower()}, - {StlSearch.SiteName.ToLower()}: '{siteName}', - {StlSearch.SiteDir.ToLower()}: '{siteDir}', - {StlSearch.SiteIds.ToLower()}: '{siteIds}', - {StlSearch.ChannelIndex.ToLower()}: '{channelIndex}', - {StlSearch.ChannelName.ToLower()}: '{channelName}', - {StlSearch.ChannelIds.ToLower()}: '{channelIds}', - {StlSearch.Type.ToLower()}: '{type}', - {StlSearch.Word.ToLower()}: '{word}', - {StlSearch.DateAttribute.ToLower()}: '{dateAttribute}', - {StlSearch.DateFrom.ToLower()}: '{dateFrom}', - {StlSearch.DateTo.ToLower()}: '{dateTo}', - {StlSearch.Since.ToLower()}: '{since}', - {StlSearch.PageNum.ToLower()}: {pageNum}, - {StlSearch.IsHighlight.ToLower()}: {isHighlight.ToString().ToLower()}, - siteid: '{siteId}', - ajaxdivid: '{ajaxDivId}', - template: '{_settingsManager.Encrypt(template)}', -}}"; - } - - public List GetSearchExlcudeAttributeNames => new List - { - StlSearch.IsAllSites.ToLower(), - StlSearch.SiteName.ToLower(), - StlSearch.SiteDir.ToLower(), - StlSearch.SiteIds.ToLower(), - StlSearch.ChannelIndex.ToLower(), - StlSearch.ChannelName.ToLower(), - StlSearch.ChannelIds.ToLower(), - StlSearch.Type.ToLower(), - StlSearch.Word.ToLower(), - StlSearch.DateAttribute.ToLower(), - StlSearch.DateFrom.ToLower(), - StlSearch.DateTo.ToLower(), - StlSearch.Since.ToLower(), - StlSearch.PageNum.ToLower(), - StlSearch.IsHighlight.ToLower(), - "siteid", - "ajaxdivid", - "template", - }; - - public string GetTriggerApiUrl(string apiUrl, int siteId, int channelId, int contentId, - int fileTemplateId, bool isRedirect) - { - return PageUtils.AddQueryString(PageUtils.Combine(apiUrl, Constants.ApiStlPrefix, Constants.RouteStlActionsTrigger), new NameValueCollection - { - {"siteId", siteId.ToString()}, - {"channelId", channelId.ToString()}, - {"contentId", contentId.ToString()}, - {"fileTemplateId", fileTemplateId.ToString()}, - {"isRedirect", isRedirect.ToString()} - }); - } - } -} diff --git a/src/SSCMS.Core/Services/PathManager.Content.cs b/src/SSCMS.Core/Services/PathManager.Content.cs index 7ecc056e0..0c8341d74 100644 --- a/src/SSCMS.Core/Services/PathManager.Content.cs +++ b/src/SSCMS.Core/Services/PathManager.Content.cs @@ -14,8 +14,7 @@ public async Task EncodeContentAsync(Site site, Channel channel, Conten { content = content.Clone(); - var tableName = _channelRepository.GetTableName(site, channel); - var tableStyles = await _tableStyleRepository.GetContentStylesAsync(channel, tableName); + var tableStyles = await _tableStyleRepository.GetContentStylesAsync(site, channel); foreach (var style in tableStyles) { if (style.InputType == InputType.Image || style.InputType == InputType.Video || style.InputType == InputType.File) @@ -54,8 +53,7 @@ public async Task DecodeContentAsync(Site site, Channel channel, Conten { content = content.Clone(); - var tableName = _channelRepository.GetTableName(site, channel); - var tableStyles = await _tableStyleRepository.GetContentStylesAsync(channel, tableName); + var tableStyles = await _tableStyleRepository.GetContentStylesAsync(site, channel); foreach (var style in tableStyles) { if (style.InputType == InputType.Image || style.InputType == InputType.Video || style.InputType == InputType.File) @@ -66,7 +64,7 @@ public async Task DecodeContentAsync(Site site, Channel channel, Conten { var extendName = ColumnsManager.GetExtendName(style.AttributeName, i); var value = content.Get(extendName); - value = await ParseNavigationUrlAsync(site, value, false); + value = await ParseSiteUrlAsync(site, value, false); content.Set(extendName, value); } @@ -105,7 +103,7 @@ public async Task EncodeTextEditorAsync(Site site, string content) // StringUtils.ReplaceHrefOrSrc(builder, url, "@"); //} - var relatedSiteUrl = ParseNavigationUrl($"~/{site.SiteDir}"); + var relatedSiteUrl = ParseUrl($"~/{site.SiteDir}"); StringUtils.ReplaceHrefOrSrc(builder, relatedSiteUrl, "@"); builder.Replace("@'@", "'@"); @@ -153,15 +151,15 @@ public async Task PutImagePathsAsync(Site site, Content content, NameValueCollec if (!string.IsNullOrEmpty(imageUrl) && IsVirtualUrl(imageUrl)) { - collection[imageUrl] = await MapPathAsync(site, imageUrl); + collection[imageUrl] = await ParseSitePathAsync(site, imageUrl); } if (!string.IsNullOrEmpty(videoUrl) && IsVirtualUrl(videoUrl)) { - collection[videoUrl] = await MapPathAsync(site, videoUrl); + collection[videoUrl] = await ParseSitePathAsync(site, videoUrl); } if (!string.IsNullOrEmpty(fileUrl) && IsVirtualUrl(fileUrl)) { - collection[fileUrl] = await MapPathAsync(site, fileUrl); + collection[fileUrl] = await ParseSitePathAsync(site, fileUrl); } var srcList = RegexUtils.GetOriginalImageSrcs(body); @@ -169,11 +167,11 @@ public async Task PutImagePathsAsync(Site site, Content content, NameValueCollec { if (IsVirtualUrl(src)) { - collection[src] = await MapPathAsync(site, src); + collection[src] = await ParseSitePathAsync(site, src); } else if (IsRelativeUrl(src)) { - collection[src] = MapPath(src); + collection[src] = ParsePath(src); } } @@ -182,11 +180,11 @@ public async Task PutImagePathsAsync(Site site, Content content, NameValueCollec { if (IsVirtualUrl(href)) { - collection[href] = await MapPathAsync(site, href); + collection[href] = await ParseSitePathAsync(site, href); } else if (IsRelativeUrl(href)) { - collection[href] = MapPath(href); + collection[href] = ParsePath(href); } } } diff --git a/src/SSCMS.Core/Services/PathManager.Pager.cs b/src/SSCMS.Core/Services/PathManager.Pager.cs index 500aac585..d2a7e5bab 100644 --- a/src/SSCMS.Core/Services/PathManager.Pager.cs +++ b/src/SSCMS.Core/Services/PathManager.Pager.cs @@ -1,6 +1,7 @@ using System.Threading.Tasks; using SSCMS.Core.StlParser.StlElement; using SSCMS.Models; +using SSCMS.Utils; namespace SSCMS.Core.Services { @@ -9,23 +10,23 @@ public partial class PathManager public async Task GetUrlInChannelPageAsync(string type, Site site, Channel node, int index, int currentPageIndex, int pageCount, bool isLocal) { var pageIndex = 0; - if (type.ToLower().Equals(StlPageItem.TypeFirstPage.ToLower()))//首页 + if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeFirstPage))//首页 { pageIndex = 0; } - else if (type.ToLower().Equals(StlPageItem.TypeLastPage.ToLower()))//末页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeLastPage))//末页 { pageIndex = pageCount - 1; } - else if (type.ToLower().Equals(StlPageItem.TypePreviousPage.ToLower()))//上一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePreviousPage))//上一页 { pageIndex = currentPageIndex - 1; } - else if (type.ToLower().Equals(StlPageItem.TypeNextPage.ToLower()))//下一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeNextPage))//下一页 { pageIndex = currentPageIndex + 1; } - else if (type.ToLower().Equals(StlPageItem.TypePageNavigation.ToLower()) || type.ToLower().Equals(StlPageItem.TypePageSelect.ToLower())) + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageNavigation) || StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageSelect)) { pageIndex = index - 1; } @@ -37,23 +38,23 @@ public async Task GetUrlInChannelPageAsync(string type, Site site, Chann public async Task GetUrlInContentPageAsync(string type, Site site, int channelId, int contentId, int index, int currentPageIndex, int pageCount, bool isLocal) { var pageIndex = 0; - if (type.ToLower().Equals(StlPageItem.TypeFirstPage.ToLower()))//首页 + if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeFirstPage))//首页 { pageIndex = 0; } - else if (type.ToLower().Equals(StlPageItem.TypeLastPage.ToLower()))//末页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeLastPage))//末页 { pageIndex = pageCount - 1; } - else if (type.ToLower().Equals(StlPageItem.TypePreviousPage.ToLower()))//上一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePreviousPage))//上一页 { pageIndex = currentPageIndex - 1; } - else if (type.ToLower().Equals(StlPageItem.TypeNextPage.ToLower()))//下一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeNextPage))//下一页 { pageIndex = currentPageIndex + 1; } - else if (type.ToLower().Equals(StlPageItem.TypePageNavigation.ToLower()) || type.ToLower().Equals(StlPageItem.TypePageSelect.ToLower())) + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageNavigation) || StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageSelect)) { pageIndex = index - 1; } @@ -66,27 +67,27 @@ public string GetClickStringInSearchPage(string type, string ajaxDivId, int inde { var clickString = string.Empty; - if (type.ToLower().Equals(StlPageItem.TypeFirstPage.ToLower()))//首页 + if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeFirstPage))//首页 { clickString = $"stlRedirect{ajaxDivId}({1})"; } - else if (type.ToLower().Equals(StlPageItem.TypeLastPage.ToLower()))//末页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeLastPage))//末页 { clickString = $"stlRedirect{ajaxDivId}({pageCount})"; } - else if (type.ToLower().Equals(StlPageItem.TypePreviousPage.ToLower()))//上一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePreviousPage))//上一页 { clickString = $"stlRedirect{ajaxDivId}({currentPageIndex})"; } - else if (type.ToLower().Equals(StlPageItem.TypeNextPage.ToLower()))//下一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeNextPage))//下一页 { clickString = $"stlRedirect{ajaxDivId}({currentPageIndex + 2})"; } - else if (type.ToLower().Equals(StlPageItem.TypePageNavigation.ToLower())) + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageNavigation)) { clickString = $"stlRedirect{ajaxDivId}({index})"; } - else if (type.ToLower().Equals(StlPageItem.TypePageSelect.ToLower())) + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageSelect)) { clickString = $"stlRedirect{ajaxDivId}(this.options[this.selectedIndex].value)"; } @@ -98,50 +99,50 @@ public async Task GetJsMethodInDynamicPageAsync(string type, Site site, { var jsMethod = string.Empty; var pageIndex = 0; - if (type.ToLower().Equals(StlPageItem.TypeFirstPage.ToLower()))//首页 + if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeFirstPage))//首页 { pageIndex = 0; } - else if (type.ToLower().Equals(StlPageItem.TypeLastPage.ToLower()))//末页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeLastPage))//末页 { pageIndex = pageCount - 1; } - else if (type.ToLower().Equals(StlPageItem.TypePreviousPage.ToLower()))//上一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePreviousPage))//上一页 { pageIndex = currentPageIndex - 1; } - else if (type.ToLower().Equals(StlPageItem.TypeNextPage.ToLower()))//下一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeNextPage))//下一页 { pageIndex = currentPageIndex + 1; } - else if (type.ToLower().Equals(StlPageItem.TypePageNavigation.ToLower()) || type.ToLower().Equals(StlPageItem.TypePageSelect.ToLower())) + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageNavigation) || StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageSelect)) { pageIndex = index - 1; } if (isPageRefresh) { - if (type.ToLower().Equals(StlPageItem.TypeFirstPage.ToLower()))//首页 + if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeFirstPage))//首页 { jsMethod = $"stlRedirect{ajaxDivId}({1})"; } - else if (type.ToLower().Equals(StlPageItem.TypeLastPage.ToLower()))//末页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeLastPage))//末页 { jsMethod = $"stlRedirect{ajaxDivId}({pageCount})"; } - else if (type.ToLower().Equals(StlPageItem.TypePreviousPage.ToLower()))//上一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePreviousPage))//上一页 { jsMethod = $"stlRedirect{ajaxDivId}({currentPageIndex})"; } - else if (type.ToLower().Equals(StlPageItem.TypeNextPage.ToLower()))//下一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeNextPage))//下一页 { jsMethod = $"stlRedirect{ajaxDivId}({currentPageIndex + 2})"; } - else if (type.ToLower().Equals(StlPageItem.TypePageNavigation.ToLower())) + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageNavigation)) { jsMethod = $"stlRedirect{ajaxDivId}({index})"; } - else if (type.ToLower().Equals(StlPageItem.TypePageSelect.ToLower())) + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageSelect)) { jsMethod = $"stlRedirect{ajaxDivId}(this.options[this.selectedIndex].value)"; } @@ -150,27 +151,27 @@ public async Task GetJsMethodInDynamicPageAsync(string type, Site site, { if (!string.IsNullOrEmpty(ajaxDivId)) { - if (type.ToLower().Equals(StlPageItem.TypeFirstPage.ToLower()))//首页 + if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeFirstPage))//首页 { jsMethod = $"stlDynamic{ajaxDivId}({1})"; } - else if (type.ToLower().Equals(StlPageItem.TypeLastPage.ToLower()))//末页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeLastPage))//末页 { jsMethod = $"stlDynamic{ajaxDivId}({pageCount})"; } - else if (type.ToLower().Equals(StlPageItem.TypePreviousPage.ToLower()))//上一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePreviousPage))//上一页 { jsMethod = $"stlDynamic{ajaxDivId}({currentPageIndex})"; } - else if (type.ToLower().Equals(StlPageItem.TypeNextPage.ToLower()))//下一页 + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypeNextPage))//下一页 { jsMethod = $"stlDynamic{ajaxDivId}({currentPageIndex + 2})"; } - else if (type.ToLower().Equals(StlPageItem.TypePageNavigation.ToLower())) + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageNavigation)) { jsMethod = $"stlDynamic{ajaxDivId}({index})"; } - else if (type.ToLower().Equals(StlPageItem.TypePageSelect.ToLower())) + else if (StringUtils.EqualsIgnoreCase(type, StlPageItem.TypePageSelect)) { jsMethod = $"stlDynamic{ajaxDivId}(this.options[this.selectedIndex].value)"; } diff --git a/src/SSCMS.Core/Services/PathManager.Plugins.cs b/src/SSCMS.Core/Services/PathManager.Plugins.cs index a9b3824e7..591af0c6a 100644 --- a/src/SSCMS.Core/Services/PathManager.Plugins.cs +++ b/src/SSCMS.Core/Services/PathManager.Plugins.cs @@ -69,24 +69,5 @@ public string GetPluginDllDirectoryPath(string pluginId) return string.Empty; } - - public string ParsePluginUrl(string pluginId, string url) - { - if (string.IsNullOrEmpty(url)) return string.Empty; - - if (PageUtils.IsProtocolUrl(url)) return url; - - if (StringUtils.StartsWith(url, "~/")) - { - return GetWebRootUrl(url.Substring(1)); - } - - if (StringUtils.StartsWith(url, "@/")) - { - return GetAdminUrl(url.Substring(1)); - } - - return GetWebRootUrl(PageUtils.Combine(DirectoryUtils.Plugins, pluginId, url)); - } } } diff --git a/src/SSCMS.Core/Services/PathManager.Root.cs b/src/SSCMS.Core/Services/PathManager.Root.cs new file mode 100644 index 000000000..327c9a7a1 --- /dev/null +++ b/src/SSCMS.Core/Services/PathManager.Root.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Specialized; +using SSCMS.Configuration; +using SSCMS.Models; +using SSCMS.Utils; + +namespace SSCMS.Core.Services +{ + public partial class PathManager + { + public string GetRootUrl(params string[] paths) + { + return PageUtils.Combine(_settingsManager.ApiHost, PageUtils.Combine(paths)); + } + + public string GetRootUrlByPath(string physicalPath) + { + var requestPath = PathUtils.GetPathDifference(_settingsManager.WebRootPath, physicalPath); + requestPath = requestPath.Replace(PathUtils.SeparatorChar, PageUtils.SeparatorChar); + return GetRootUrl(requestPath); + } + + public string GetTemporaryFilesUrl(params string[] paths) + { + return GetSiteFilesUrl(DirectoryUtils.SiteFiles.TemporaryFiles, PageUtils.Combine(paths)); + } + + public string GetSiteTemplatesUrl(string relatedUrl) + { + return GetRootUrl(DirectoryUtils.SiteFiles.DirectoryName, DirectoryUtils.SiteFiles.SiteTemplates.DirectoryName, relatedUrl); + } + + public string ParseUrl(string virtualUrl) + { + if (string.IsNullOrEmpty(virtualUrl)) return string.Empty; + if (PageUtils.IsAbsoluteUrl(virtualUrl)) return virtualUrl; + + virtualUrl = virtualUrl.StartsWith("~") ? GetRootUrl(virtualUrl.Substring(1)) : virtualUrl; + virtualUrl = virtualUrl.Replace(PathUtils.SeparatorChar, PageUtils.SeparatorChar); + virtualUrl = virtualUrl.Replace(PageUtils.DoubleSeparator, PageUtils.SingleSeparator); + return virtualUrl; + } + + public string ParsePath(string virtualPath) + { + virtualPath = PathUtils.RemovePathInvalidChar(virtualPath); + if (!string.IsNullOrEmpty(virtualPath)) + { + if (virtualPath.StartsWith("~")) + { + virtualPath = virtualPath.Substring(1); + } + virtualPath = PageUtils.Combine("~", virtualPath); + } + else + { + virtualPath = "~/"; + } + var rootPath = WebRootPath; + + virtualPath = !string.IsNullOrEmpty(virtualPath) ? virtualPath.Substring(2) : string.Empty; + var retVal = PathUtils.Combine(rootPath, virtualPath) ?? string.Empty; + + return retVal.Replace(PageUtils.SeparatorChar, PathUtils.SeparatorChar); + } + + public string ParsePath(string directoryPath, string virtualPath) + { + var resolvedPath = virtualPath; + if (string.IsNullOrEmpty(virtualPath)) + { + virtualPath = "@"; + } + if (!virtualPath.StartsWith("@") && !virtualPath.StartsWith("~")) + { + virtualPath = "@" + virtualPath; + } + if (virtualPath.StartsWith("@")) + { + if (string.IsNullOrEmpty(directoryPath)) + { + resolvedPath = string.Concat("~", virtualPath.Substring(1)); + } + else + { + return PageUtils.Combine(directoryPath, virtualPath.Substring(1)); + } + } + return ParsePath(resolvedPath); + } + + public string GetSiteFilesUrl(params string[] paths) + { + return GetRootUrl(DirectoryUtils.SiteFiles.DirectoryName, PageUtils.Combine(paths)); + } + + public string GetAdministratorUploadUrl(int userId, params string[] paths) + { + return GetSiteFilesUrl(DirectoryUtils.SiteFiles.Administrators, + PageUtils.Combine(userId.ToString(), PageUtils.Combine(paths))); + } + + public string GetUserUploadUrl(int userId, params string[] paths) + { + return GetSiteFilesUrl(DirectoryUtils.SiteFiles.Users, + PageUtils.Combine(userId.ToString(), PageUtils.Combine(paths))); + } + + public string GetHomeUploadUrl(params string[] paths) + { + return GetSiteFilesUrl(DirectoryUtils.SiteFiles.Home, PageUtils.Combine(paths)); + } + + public string DefaultAvatarUrl => GetHomeUploadUrl("default_avatar.png"); + + public string GetUserUploadFileName(string filePath) + { + var dt = DateTime.Now; + return $"{dt.Day}{dt.Hour}{dt.Minute}{dt.Second}{dt.Millisecond}{PathUtils.GetExtension(filePath)}"; + } + + public string GetUserUploadUrl(int userId, string relatedUrl) + { + return GetHomeUploadUrl(userId.ToString(), relatedUrl); + } + + public string GetUserAvatarUrl(User user) + { + var imageUrl = user?.AvatarUrl; + + if (!string.IsNullOrEmpty(imageUrl)) + { + return PageUtils.IsProtocolUrl(imageUrl) ? imageUrl : GetUserUploadUrl(user.Id, imageUrl); + } + + return DefaultAvatarUrl; + } + + public string GetRootPath(params string[] paths) + { + return PathUtils.Combine(_settingsManager.WebRootPath, PathUtils.Combine(paths)); + } + + public string GetContentRootPath(params string[] paths) + { + return PathUtils.Combine(_settingsManager.ContentRootPath, PathUtils.Combine(paths)); + } + + public string GetSiteFilesPath(params string[] paths) + { + var path = PathUtils.Combine(_settingsManager.WebRootPath, DirectoryUtils.SiteFiles.DirectoryName, PathUtils.Combine(paths)); + return path; + } + + public string GetAdministratorUploadPath(int userId, params string[] paths) + { + var path = GetSiteFilesPath(DirectoryUtils.SiteFiles.Administrators, PathUtils.Combine(userId.ToString(), PathUtils.Combine(paths))); + return path; + } + + public string GetUserUploadPath(int userId, params string[] paths) + { + var path = GetSiteFilesPath(DirectoryUtils.SiteFiles.Users, PathUtils.Combine(userId.ToString(), PathUtils.Combine(paths))); + return path; + } + + public string GetHomeUploadPath(params string[] paths) + { + var path = GetSiteFilesPath(DirectoryUtils.SiteFiles.Home, PathUtils.Combine(paths)); + return path; + } + + public string GetTemporaryFilesPath(params string[] paths) + { + var path = GetSiteFilesPath(DirectoryUtils.SiteFiles.TemporaryFiles, PathUtils.Combine(paths)); + return path; + } + + public string GetUserUploadPath(int userId, string relatedPath) + { + return GetHomeUploadPath(userId.ToString(), relatedPath); + } + + public string GetApiUrl(params string[] paths) + { + return PageUtils.Combine(_settingsManager.ApiHost, Constants.ApiPrefix, PathUtils.Combine(paths)); + } + + public string GetDownloadApiUrl(int siteId, int channelId, int contentId, string fileUrl) + { + return PageUtils.AddQueryString(PageUtils.Combine(_settingsManager.ApiHost, Constants.ApiPrefix, Constants.ApiStlPrefix, Constants.RouteStlActionsDownload), new NameValueCollection + { + {"siteId", siteId.ToString()}, + {"channelId", channelId.ToString()}, + {"contentId", contentId.ToString()}, + {"fileUrl", _settingsManager.Encrypt(fileUrl)} + }); + } + + public string GetDownloadApiUrl(int siteId, string fileUrl) + { + return PageUtils.AddQueryString(PageUtils.Combine(_settingsManager.ApiHost, Constants.ApiPrefix, Constants.ApiStlPrefix, Constants.RouteStlActionsDownload), new NameValueCollection + { + {"siteId", siteId.ToString()}, + {"fileUrl", _settingsManager.Encrypt(fileUrl)} + }); + } + + public string GetDownloadApiUrl(bool isInner, string filePath) + { + return PageUtils.AddQueryString(PageUtils.Combine(_settingsManager.ApiHost, Constants.ApiPrefix, Constants.ApiStlPrefix, Constants.RouteStlActionsDownload), new NameValueCollection + { + {"filePath", _settingsManager.Encrypt(filePath)} + }); + } + + public string GetDynamicApiUrl() + { + return PageUtils.Combine(_settingsManager.ApiHost, Constants.ApiPrefix, Constants.ApiStlPrefix, Constants.RouteStlActionsDynamic); + } + + public string GetIfApiUrl() + { + return PageUtils.Combine(_settingsManager.ApiHost, Constants.ApiPrefix, Constants.ApiStlPrefix, Constants.RouteStlRouteActionsIf); + } + + public string GetPageContentsApiUrl() + { + return PageUtils.Combine(_settingsManager.ApiHost, Constants.ApiPrefix, Constants.ApiStlPrefix, Constants.RouteStlActionsPageContents); + } + + public string GetPageContentsApiParameters(int siteId, int pageChannelId, int templateId, int totalNum, int pageCount, + int currentPageIndex, string stlPageContentsElement) + { + return $@" +{{ + siteId: {siteId}, + pageChannelId: {pageChannelId}, + templateId: {templateId}, + totalNum: {totalNum}, + pageCount: {pageCount}, + currentPageIndex: {currentPageIndex}, + stlPageContentsElement: '{_settingsManager.Encrypt(stlPageContentsElement)}' +}}"; + } + + public string GetTriggerApiUrl(int siteId, int channelId, int contentId, + int fileTemplateId, bool isRedirect) + { + return PageUtils.AddQueryString(PageUtils.Combine(_settingsManager.ApiHost, Constants.ApiPrefix, Constants.ApiStlPrefix, Constants.RouteStlActionsTrigger), new NameValueCollection + { + {"siteId", siteId.ToString()}, + {"channelId", channelId.ToString()}, + {"contentId", contentId.ToString()}, + {"fileTemplateId", fileTemplateId.ToString()}, + {"isRedirect", isRedirect.ToString()} + }); + } + } +} diff --git a/src/SSCMS.Core/Services/PathManager.Site.cs b/src/SSCMS.Core/Services/PathManager.Site.cs index 40a1bbb97..62de0579e 100644 --- a/src/SSCMS.Core/Services/PathManager.Site.cs +++ b/src/SSCMS.Core/Services/PathManager.Site.cs @@ -3,8 +3,8 @@ using System.Linq; using System.Threading.Tasks; using Datory; +using SSCMS.Configuration; using SSCMS.Core.Utils; -using SSCMS.Core.Utils.Images; using SSCMS.Core.Utils.PathRules; using SSCMS.Dto; using SSCMS.Enums; @@ -15,62 +15,37 @@ namespace SSCMS.Core.Services { public partial class PathManager { - // 系统根目录访问地址 - public string GetWebRootUrl(params string[] paths) - { - return PageUtils.Combine("/", PathUtils.Combine(paths)); - } - - public string GetWebRootPath(params string[] paths) - { - return PathUtils.Combine(_settingsManager.WebRootPath, PathUtils.Combine(paths)); - } - - public string GetContentRootPath(params string[] paths) - { - return PathUtils.Combine(_settingsManager.ContentRootPath, PathUtils.Combine(paths)); - } - - public string GetTemporaryFilesUrl(string relatedUrl) - { - return PageUtils.Combine($"/{DirectoryUtils.SiteFilesDirectoryName}", DirectoryUtils.SiteFiles.TemporaryFiles, relatedUrl); - } - - public string GetSiteTemplatesUrl(string relatedUrl) - { - return PageUtils.Combine($"/{DirectoryUtils.SiteFilesDirectoryName}", DirectoryUtils.SiteTemplates.DirectoryName, relatedUrl); - } - - public string GetRootUrlByPhysicalPath(string physicalPath) + //根据发布系统属性判断是否为相对路径并返回解析后路径 + public async Task ParseSiteUrlAsync(Site site, string virtualUrl, bool isLocal) { - var requestPath = PathUtils.GetPathDifference(_settingsManager.WebRootPath, physicalPath); - requestPath = requestPath.Replace(PathUtils.SeparatorChar, PageUtils.SeparatorChar); - return GetWebRootUrl(requestPath); - } + if (string.IsNullOrEmpty(virtualUrl)) return string.Empty; - public string ParseNavigationUrl(string url) - { - if (string.IsNullOrEmpty(url)) return string.Empty; + if (site != null && StringUtils.StartsWith(virtualUrl, "@")) + { + return await GetSiteUrlAsync(site, virtualUrl.Substring(1), isLocal); + } - url = url.StartsWith("~") ? PageUtils.Combine("/", url.Substring(1)) : url; - url = url.Replace(PathUtils.SeparatorChar, PageUtils.SeparatorChar); - return url; + return ParseUrl(virtualUrl); } - //根据发布系统属性判断是否为相对路径并返回解析后路径 - public async Task ParseNavigationUrlAsync(Site site, string url, bool isLocal) + public async Task ParseSitePathAsync(Site site, string virtualPath) { - if (string.IsNullOrEmpty(url)) return string.Empty; + var resolvedPath = virtualPath; + if (string.IsNullOrEmpty(virtualPath)) + { + virtualPath = "@"; + } + if (!virtualPath.StartsWith("@") && !virtualPath.StartsWith("~")) + { + virtualPath = "@" + virtualPath; + } + if (!virtualPath.StartsWith("@")) return ParsePath(resolvedPath); if (site != null) { - if (!string.IsNullOrEmpty(url) && url.StartsWith("@")) - { - return await GetSiteUrlAsync(site, url.Substring(1), isLocal); - } - return ParseNavigationUrl(url); + return await GetSitePathAsync(site, virtualPath.Substring(1)); } - return ParseNavigationUrl(url); + return ParsePath(resolvedPath); } public async Task GetSiteUrlAsync(Site site, bool isLocal) @@ -99,6 +74,18 @@ public async Task GetSiteUrlByPhysicalPathAsync(Site site, string physic return await GetSiteUrlAsync(site, requestPath, isLocal); } + public async Task GetVirtualUrlByPhysicalPathAsync(Site site, string physicalPath) + { + if (site == null || string.IsNullOrEmpty(physicalPath)) return await GetWebUrlAsync(site); + + var sitePath = await GetSitePathAsync(site); + var requestPath = StringUtils.StartsWithIgnoreCase(physicalPath, sitePath) + ? StringUtils.ReplaceStartsWithIgnoreCase(physicalPath, sitePath, string.Empty) + : string.Empty; + + return AddVirtualToUrl(requestPath); + } + public async Task GetRemoteSiteUrlAsync(Site site, string requestPath) { var url = await GetWebUrlAsync(site); @@ -143,7 +130,7 @@ public async Task GetLocalSiteUrlAsync(Site site, string requestPath = n string url; if (site.ParentId == 0) { - url = ParseNavigationUrl($"~/{(site.Root ? string.Empty : site.SiteDir)}"); + url = ParseUrl($"~/{(site.Root ? string.Empty : site.SiteDir)}"); } else { @@ -177,50 +164,45 @@ public async Task GetLocalSiteUrlAsync(Site site, string requestPath = n return url; } - public string GetLocalSiteUrl(int siteId) + public string GetPreviewSiteUrl(int siteId) { - var apiUrl = GetInnerApiUrl(Constants.RoutePreview); + var apiUrl = PageUtils.Combine(_settingsManager.ApiHost, Constants.RoutePreview); apiUrl = apiUrl.Replace("{siteId}", siteId.ToString()); return apiUrl; } - public string GetLocalChannelUrl(int siteId, int channelId) + public string GetPreviewChannelUrl(int siteId, int channelId) { - var apiUrl = GetInnerApiUrl(Constants.RoutePreviewChannel); + var apiUrl = PageUtils.Combine(_settingsManager.ApiHost, Constants.RoutePreviewChannel); apiUrl = apiUrl.Replace("{siteId}", siteId.ToString()); apiUrl = apiUrl.Replace("{channelId}", channelId.ToString()); return apiUrl; } - public string GetLocalContentUrl(int siteId, int channelId, int contentId) + public string GetPreviewContentUrl(int siteId, int channelId, int contentId, bool isPreview = false) { - var apiUrl = GetInnerApiUrl(Constants.RoutePreviewContent); + var apiUrl = PageUtils.Combine(_settingsManager.ApiHost, Constants.RoutePreviewContent); apiUrl = apiUrl.Replace("{siteId}", siteId.ToString()); apiUrl = apiUrl.Replace("{channelId}", channelId.ToString()); apiUrl = apiUrl.Replace("{contentId}", contentId.ToString()); - return apiUrl; - } - - public string GetContentPreviewUrl(int siteId, int channelId, int contentId, int previewId) - { - if (contentId == 0) + if (isPreview) { - contentId = previewId; + apiUrl += "?isPreview=true"; } - return $"{GetLocalContentUrl(siteId, channelId, contentId)}?isPreview=true&previewId={previewId}"; + return apiUrl; } - public string GetLocalFileUrl(int siteId, int fileTemplateId) + public string GetPreviewFileUrl(int siteId, int fileTemplateId) { - var apiUrl = GetInnerApiUrl(Constants.RoutePreviewFile); + var apiUrl = PageUtils.Combine(_settingsManager.ApiHost, Constants.RoutePreviewFile); apiUrl = apiUrl.Replace("{siteId}", siteId.ToString()); apiUrl = apiUrl.Replace("{fileTemplateId}", fileTemplateId.ToString()); return apiUrl; } - public string GetLocalSpecialUrl(int siteId, int specialId) + public string GetPreviewSpecialUrl(int siteId, int specialId) { - var apiUrl = GetInnerApiUrl(Constants.RoutePreviewSpecial); + var apiUrl = PageUtils.Combine(_settingsManager.ApiHost, Constants.RoutePreviewSpecial); apiUrl = apiUrl.Replace("{siteId}", siteId.ToString()); apiUrl = apiUrl.Replace("{specialId}", specialId.ToString()); return apiUrl; @@ -233,8 +215,8 @@ public async Task GetIndexPageUrlAsync(Site site, bool isLocal) var createdFileFullName = await _templateRepository.GetCreatedFileFullNameAsync(indexTemplateId); var url = isLocal - ? GetLocalSiteUrl(site.Id) - : await ParseNavigationUrlAsync(site, createdFileFullName, false); + ? GetPreviewSiteUrl(site.Id) + : await ParseSiteUrlAsync(site, createdFileFullName, false); return RemoveDefaultFileName(site, url); } @@ -244,8 +226,8 @@ public async Task GetFileUrlAsync(Site site, int fileTemplateId, bool is var createdFileFullName = await _templateRepository.GetCreatedFileFullNameAsync(fileTemplateId); var url = isLocal - ? GetLocalFileUrl(site.Id, fileTemplateId) - : await ParseNavigationUrlAsync(site, createdFileFullName, false); + ? GetPreviewFileUrl(site.Id, fileTemplateId) + : await ParseSiteUrlAsync(site, createdFileFullName, false); return RemoveDefaultFileName(site, url); } @@ -267,7 +249,7 @@ public async Task GetContentUrlByIdAsync(Site site, Content contentCurre if (isLocal) { - return GetLocalContentUrl(site.Id, contentCurrent.ChannelId, + return GetPreviewContentUrl(site.Id, contentCurrent.ChannelId, contentCurrent.Id); } @@ -275,7 +257,7 @@ public async Task GetContentUrlByIdAsync(Site site, Content contentCurre var referenceId = contentCurrent.ReferenceId; var linkUrl = contentCurrent.LinkUrl; var channelId = contentCurrent.ChannelId; - if (referenceId > 0 && TranslateContentType.ReferenceContent.GetValue() == contentCurrent.Get(ColumnsManager.TranslateContentType)) + if (referenceId > 0 && TranslateType.ReferenceContent.GetValue() == contentCurrent.Get(ColumnsManager.TranslateContentType)) { if (sourceId > 0 && await _channelRepository.IsExistsAsync(sourceId)) { @@ -314,7 +296,7 @@ public async Task GetContentUrlByIdAsync(Site site, Content contentCurre if (!string.IsNullOrEmpty(linkUrl)) { - return await ParseNavigationUrlAsync(site, linkUrl, false); + return await ParseSiteUrlAsync(site, linkUrl, false); } var rules = new ContentFilePathRules(this, _databaseManager); @@ -326,12 +308,12 @@ public async Task GetContentUrlByIdAsync(Site site, int channelId, int c { if (isLocal) { - return GetLocalContentUrl(site.Id, channelId, contentId); + return GetPreviewContentUrl(site.Id, channelId, contentId); } var contentInfoCurrent = await _contentRepository.GetAsync(site, channelId, contentId); - if (referenceId > 0 && TranslateContentType.ReferenceContent.GetValue() == contentInfoCurrent.Get(ColumnsManager.TranslateContentType)) + if (referenceId > 0 && TranslateType.ReferenceContent.GetValue() == contentInfoCurrent.Get(ColumnsManager.TranslateContentType)) { if (sourceId > 0 && await _channelRepository.IsExistsAsync(sourceId)) { @@ -361,7 +343,7 @@ public async Task GetContentUrlByIdAsync(Site site, int channelId, int c } if (!string.IsNullOrEmpty(linkUrl)) { - return await ParseNavigationUrlAsync(site, linkUrl, false); + return await ParseSiteUrlAsync(site, linkUrl, false); } var rules = new ContentFilePathRules(this, _databaseManager); @@ -394,11 +376,11 @@ public async Task GetChannelUrlNotComputedAsync(Site site, int channelId var channelUrl = await rules.ParseAsync(site, channelId); return await GetSiteUrlAsync(site, channelUrl, isLocal); } - return await ParseNavigationUrlAsync(site, AddVirtualToPath(filePath), isLocal); + return await ParseSiteUrlAsync(site, AddVirtualToPath(filePath), isLocal); } } - return await ParseNavigationUrlAsync(site, linkUrl, isLocal); + return await ParseSiteUrlAsync(site, linkUrl, isLocal); } //得到栏目经过计算后的连接地址 @@ -408,7 +390,7 @@ public async Task GetChannelUrlAsync(Site site, Channel channel, bool is if (isLocal) { - return GetLocalChannelUrl(site.Id, channel.Id); + return GetPreviewChannelUrl(site.Id, channel.Id); } var url = string.Empty; @@ -554,6 +536,8 @@ public string AddVirtualToUrl(string url) var resolvedUrl = url; if (string.IsNullOrEmpty(url) || PageUtils.IsProtocolUrl(url)) return resolvedUrl; + url = url.Replace(PathUtils.SeparatorChar, PageUtils.SeparatorChar); + if (!url.StartsWith("@") && !url.StartsWith("~")) { resolvedUrl = PageUtils.Combine("@/", url); @@ -565,7 +549,7 @@ public string GetVirtualUrl(Site site, string url) { if (string.IsNullOrEmpty(url)) return string.Empty; - var relatedSiteUrl = ParseNavigationUrl($"~/{site.SiteDir}"); + var relatedSiteUrl = ParseUrl($"~/{site.SiteDir}"); var virtualUrl = StringUtils.ReplaceStartsWith(url, relatedSiteUrl, "@/"); return StringUtils.ReplaceStartsWith(virtualUrl, "@//", "@/"); } @@ -584,37 +568,6 @@ public bool IsRelativeUrl(string url) return url.StartsWith("/"); } - public string GetSiteFilesUrl(string relatedUrl) - { - return PageUtils.Combine($"/{DirectoryUtils.SiteFilesDirectoryName}", relatedUrl); - } - - public string GetSiteFilesUrl(string apiUrl, string relatedUrl) - { - if (string.IsNullOrEmpty(apiUrl)) - { - apiUrl = "/api"; - } - apiUrl = apiUrl.Trim().ToLower(); - if (apiUrl == "/api") - { - apiUrl = "/"; - } - else if (apiUrl.EndsWith("/api")) - { - apiUrl = apiUrl.Substring(0, apiUrl.LastIndexOf("/api", StringComparison.Ordinal)); - } - else if (apiUrl.EndsWith("/api/")) - { - apiUrl = apiUrl.Substring(0, apiUrl.LastIndexOf("/api/", StringComparison.Ordinal)); - } - if (string.IsNullOrEmpty(apiUrl)) - { - apiUrl = "/"; - } - return PageUtils.Combine(apiUrl, DirectoryUtils.SiteFilesDirectoryName, relatedUrl); - } - public List> GetLinkTypeSelects() { return new List> @@ -643,7 +596,7 @@ public async Task GetSitePathAsync(Site site, params string[] paths) { if (site == null) { - return GetWebRootPath(paths); + return GetRootPath(paths); } string sitePath; @@ -671,7 +624,7 @@ public async Task GetSitePathAsync(int siteId, params string[] paths) { if (siteId == 0) { - return GetWebRootPath(paths); + return GetRootPath(paths); } var site = await _siteRepository.GetAsync(siteId); return await GetSitePathAsync(site, paths); @@ -702,7 +655,7 @@ public async Task GetIndexPageFilePathAsync(Site site, string createFile } } - var filePath = await MapPathAsync(site, createFileFullName); + var filePath = await ParseSitePathAsync(site, createFileFullName); if (currentPageIndex != 0) { @@ -838,19 +791,7 @@ public string GetUploadFileName(Site site, string filePath) isUploadChangeFileName = site.IsVideoUploadChangeFileName; } - return GetUploadFileName(filePath, isUploadChangeFileName); - } - - public string GetUploadFileName(string filePath, bool isUploadChangeFileName) - { - if (isUploadChangeFileName) - { - return $"{StringUtils.GetShortGuid(false)}{PathUtils.GetExtension(filePath)}"; - } - - var fileName = PathUtils.GetFileNameWithoutExtension(filePath); - fileName = PathUtils.GetSafeFilename(fileName); - return $"{fileName}{PathUtils.GetExtension(filePath)}"; + return PathUtils.GetUploadFileName(filePath, isUploadChangeFileName); } private bool Contains(string text, string inner) @@ -860,8 +801,8 @@ private bool Contains(string text, string inner) public async Task GetSiteAsync(string path) { - var directoryPath = DirectoryUtils.GetDirectoryPath(path).ToLower().Trim(' ', '/', '\\'); - var applicationPath = _settingsManager.WebRootPath.ToLower().Trim(' ', '/', '\\'); + var directoryPath = StringUtils.ToLower(DirectoryUtils.GetDirectoryPath(path)).Trim(' ', '/', '\\'); + var applicationPath = StringUtils.ToLower(_settingsManager.WebRootPath).Trim(' ', '/', '\\'); var directoryDir = StringUtils.ReplaceStartsWith(directoryPath, applicationPath, string.Empty).Trim(' ', '/', '\\'); if (directoryDir == string.Empty) return null; @@ -876,7 +817,7 @@ public async Task GetSiteAsync(string path) } else { - if (Contains(directoryDir, site.SiteDir.ToLower())) + if (Contains(directoryDir, StringUtils.ToLower(site.SiteDir))) { return site; } @@ -889,8 +830,8 @@ public async Task GetSiteAsync(string path) public async Task GetSiteDirAsync(string path) { var siteDir = string.Empty; - var directoryPath = DirectoryUtils.GetDirectoryPath(path).ToLower().Trim(' ', '/', '\\'); - var applicationPath = _settingsManager.WebRootPath.ToLower().Trim(' ', '/', '\\'); + var directoryPath = StringUtils.ToLower(DirectoryUtils.GetDirectoryPath(path)).Trim(' ', '/', '\\'); + var applicationPath = StringUtils.ToLower(_settingsManager.WebRootPath).Trim(' ', '/', '\\'); var directoryDir = StringUtils.ReplaceStartsWith(directoryPath, applicationPath, string.Empty).Trim(' ', '/', '\\'); if (directoryDir == string.Empty) { @@ -902,7 +843,7 @@ public async Task GetSiteDirAsync(string path) { if (site?.Root != false) continue; - if (Contains(directoryDir, site.SiteDir.ToLower())) + if (Contains(directoryDir, StringUtils.ToLower(site.SiteDir))) { siteDir = site.SiteDir; } @@ -940,73 +881,6 @@ public string AddVirtualToPath(string path) return resolvedPath; } - public async Task MapPathAsync(Site site, string virtualPath) - { - var resolvedPath = virtualPath; - if (string.IsNullOrEmpty(virtualPath)) - { - virtualPath = "@"; - } - if (!virtualPath.StartsWith("@") && !virtualPath.StartsWith("~")) - { - virtualPath = "@" + virtualPath; - } - if (!virtualPath.StartsWith("@")) return MapPath(resolvedPath); - - if (site != null) - { - return await GetSitePathAsync(site, virtualPath.Substring(1)); - } - return MapPath(resolvedPath); - } - - public async Task MapPathAsync(Site site, string virtualPath, bool isCopyToSite) - { - if (!isCopyToSite) return await MapPathAsync(site, virtualPath); - - var resolvedPath = virtualPath; - if (string.IsNullOrEmpty(virtualPath)) - { - virtualPath = "@"; - } - if (!virtualPath.StartsWith("@") && !virtualPath.StartsWith("~")) - { - virtualPath = "@" + virtualPath; - } - if (!virtualPath.StartsWith("@")) return MapPath(resolvedPath); - - if (site != null) - { - return await GetSitePathAsync(site, virtualPath.Substring(1)); - } - return MapPath(resolvedPath); - } - - public string MapPath(string directoryPath, string virtualPath) - { - var resolvedPath = virtualPath; - if (string.IsNullOrEmpty(virtualPath)) - { - virtualPath = "@"; - } - if (!virtualPath.StartsWith("@") && !virtualPath.StartsWith("~")) - { - virtualPath = "@" + virtualPath; - } - if (virtualPath.StartsWith("@")) - { - if (string.IsNullOrEmpty(directoryPath)) - { - resolvedPath = string.Concat("~", virtualPath.Substring(1)); - } - else - { - return PageUtils.Combine(directoryPath, virtualPath.Substring(1)); - } - } - return MapPath(resolvedPath); - } - //将编辑器中图片上传至本机 public async Task SaveImageAsync(Site site, string content) { @@ -1035,7 +909,7 @@ public async Task SaveImageAsync(Site site, string content) { if (!FileUtils.IsFileExists(filePath)) { - WebClientUtils.SaveRemoteFileToLocal(originalImageSrc, filePath); + WebClientUtils.Download(originalImageSrc, filePath); if (FileUtils.IsImage(PathUtils.GetExtension(fileName))) { await AddWaterMarkAsync(site, filePath); @@ -1055,19 +929,19 @@ public async Task SaveImageAsync(Site site, string content) public string GetTemporaryFilesPath(string relatedPath) { relatedPath = PathUtils.RemoveParentPath(relatedPath); - return PathUtils.Combine(_settingsManager.WebRootPath, DirectoryUtils.SiteFilesDirectoryName, DirectoryUtils.SiteFiles.TemporaryFiles, relatedPath); + return PathUtils.Combine(_settingsManager.WebRootPath, DirectoryUtils.SiteFiles.DirectoryName, DirectoryUtils.SiteFiles.TemporaryFiles, relatedPath); } public string GetSiteTemplatesPath(string relatedPath) { relatedPath = PathUtils.RemoveParentPath(relatedPath); - return PathUtils.Combine(_settingsManager.WebRootPath, DirectoryUtils.SiteFilesDirectoryName, DirectoryUtils.SiteTemplates.DirectoryName, relatedPath); + return PathUtils.Combine(_settingsManager.WebRootPath, DirectoryUtils.SiteFiles.DirectoryName, DirectoryUtils.SiteFiles.SiteTemplates.DirectoryName, relatedPath); } public string GetSiteTemplateMetadataPath(string siteTemplatePath, string relatedPath) { relatedPath = PathUtils.RemoveParentPath(relatedPath); - return PathUtils.Combine(siteTemplatePath, DirectoryUtils.SiteTemplates.SiteTemplateMetadata, relatedPath); + return PathUtils.Combine(siteTemplatePath, DirectoryUtils.SiteFiles.SiteTemplates.SiteTemplateMetadata, relatedPath); } public async Task GetChannelFilePathRuleAsync(Site site, int channelId) @@ -1146,7 +1020,7 @@ public async Task GetChannelPageFilePathAsync(Site site, int channelId, filePath = await rules.ParseAsync(site, channelId); } - filePath = await MapPathAsync(site, filePath);// PathUtils.Combine(sitePath, filePath); + filePath = await ParseSitePathAsync(site, filePath);// PathUtils.Combine(sitePath, filePath); if (PathUtils.IsDirectoryPath(filePath)) { filePath = PathUtils.Combine(filePath, channelId + ".html"); @@ -1174,7 +1048,7 @@ public async Task GetContentPageFilePathAsync(Site site, int channelId, var rules = new ContentFilePathRules(this, _databaseManager); var filePath = await rules.ParseAsync(site, channelId, content); - filePath = await MapPathAsync(site, filePath); + filePath = await ParseSitePathAsync(site, filePath); if (PathUtils.IsDirectoryPath(filePath)) { filePath = PathUtils.Combine(filePath, content.Id + ".html"); @@ -1210,9 +1084,19 @@ public bool IsVideoSizeAllowed(Site site, int contentLength) return contentLength <= site.VideoUploadTypeMaxSize * 1024; } + public bool IsAudioExtensionAllowed(Site site, string fileExtension) + { + return PathUtils.IsFileExtensionAllowed(site.AudioUploadExtensions, fileExtension); + } + + public bool IsAudioSizeAllowed(Site site, int contentLength) + { + return contentLength <= site.AudioUploadTypeMaxSize * 1024; + } + public bool IsFileExtensionAllowed(Site site, string fileExtension) { - var typeCollection = site.FileUploadExtensions + "," + site.ImageUploadExtensions + "," + site.VideoUploadExtensions; + var typeCollection = site.FileUploadExtensions + "," + site.ImageUploadExtensions + "," + site.VideoUploadExtensions + "," + site.AudioUploadExtensions; return PathUtils.IsFileExtensionAllowed(typeCollection, fileExtension); } @@ -1227,11 +1111,18 @@ public bool IsUploadExtensionAllowed(UploadType uploadType, Site site, string fi { return IsImageExtensionAllowed(site, fileExtension); } - else if (uploadType == UploadType.Video) + + if (uploadType == UploadType.Video) { return IsVideoExtensionAllowed(site, fileExtension); } - else if (uploadType == UploadType.File) + + if (uploadType == UploadType.Audio) + { + return IsAudioExtensionAllowed(site, fileExtension); + } + + if (uploadType == UploadType.File) { return IsFileExtensionAllowed(site, fileExtension); } @@ -1240,14 +1131,24 @@ public bool IsUploadExtensionAllowed(UploadType uploadType, Site site, string fi public bool IsUploadSizeAllowed(UploadType uploadType, Site site, int contentLength) { - switch (uploadType) + if (uploadType == UploadType.Image) + { + return IsImageSizeAllowed(site, contentLength); + } + + if (uploadType == UploadType.Video) { - case UploadType.Image: - return IsImageSizeAllowed(site, contentLength); - case UploadType.Video: - return IsVideoSizeAllowed(site, contentLength); - case UploadType.File: - return IsFileSizeAllowed(site, contentLength); + return IsVideoSizeAllowed(site, contentLength); + } + + if (uploadType == UploadType.Audio) + { + return IsAudioSizeAllowed(site, contentLength); + } + + if (uploadType == UploadType.File) + { + return IsFileSizeAllowed(site, contentLength); } return false; } @@ -1258,12 +1159,7 @@ public string GetBinDirectoryPath(string relatedPath) return PathUtils.Combine(_settingsManager.WebRootPath, DirectoryUtils.BinDirectoryName, relatedPath); } - public string PhysicalSiteFilesPath => PathUtils.Combine(_settingsManager.WebRootPath, DirectoryUtils.SiteFilesDirectoryName); - - public string GetLibraryFilePath(string virtualUrl) - { - return PathUtils.Combine(_settingsManager.WebRootPath, virtualUrl); - } + public string PhysicalSiteFilesPath => PathUtils.Combine(_settingsManager.WebRootPath, DirectoryUtils.SiteFiles.DirectoryName); public async Task DeleteSiteFilesAsync(Site site) { @@ -1403,8 +1299,8 @@ public async Task ChangeToSubSiteAsync(Site site, string siteDir, IList public bool IsSystemDirectory(string directoryName) { - return StringUtils.EqualsIgnoreCase(directoryName, DirectoryUtils.HomeDirectoryName) || - StringUtils.EqualsIgnoreCase(directoryName, DirectoryUtils.SiteFilesDirectoryName); + return StringUtils.EqualsIgnoreCase(directoryName, DirectoryUtils.SiteFiles.Home) || + StringUtils.EqualsIgnoreCase(directoryName, DirectoryUtils.SiteFiles.DirectoryName); } public async Task AddWaterMarkAsync(Site site, string imagePath) @@ -1420,7 +1316,7 @@ public async Task AddWaterMarkAsync(Site site, string imagePath) { if (!string.IsNullOrEmpty(site.WaterMarkImagePath)) { - ImageUtils.AddImageWaterMark(imagePath, await MapPathAsync(site, site.WaterMarkImagePath), site.WaterMarkPosition, site.WaterMarkTransparency, site.WaterMarkMinWidth, site.WaterMarkMinHeight); + OldImageUtils.AddImageWaterMark(imagePath, await ParseSitePathAsync(site, site.WaterMarkImagePath), site.WaterMarkPosition, site.WaterMarkTransparency, site.WaterMarkMinWidth, site.WaterMarkMinHeight); } } else @@ -1428,7 +1324,7 @@ public async Task AddWaterMarkAsync(Site site, string imagePath) if (!string.IsNullOrEmpty(site.WaterMarkFormatString)) { var now = DateTime.Now; - ImageUtils.AddTextWaterMark(imagePath, string.Format(site.WaterMarkFormatString, DateUtils.GetDateString(now), DateUtils.GetTimeString(now)), site.WaterMarkFontName, site.WaterMarkFontSize, site.WaterMarkPosition, site.WaterMarkTransparency, site.WaterMarkMinWidth, site.WaterMarkMinHeight); + OldImageUtils.AddTextWaterMark(imagePath, string.Format(site.WaterMarkFormatString, DateUtils.GetDateString(now), DateUtils.GetTimeString(now)), site.WaterMarkFontName, site.WaterMarkFontSize, site.WaterMarkPosition, site.WaterMarkTransparency, site.WaterMarkMinWidth, site.WaterMarkMinHeight); } } } @@ -1444,8 +1340,8 @@ public async Task MoveFileAsync(Site sourceSite, Site destSite, string relatedUr { if (!string.IsNullOrEmpty(relatedUrl)) { - var sourceFilePath = await MapPathAsync(sourceSite, relatedUrl); - var descFilePath = await MapPathAsync(destSite, relatedUrl); + var sourceFilePath = await ParseSitePathAsync(sourceSite, relatedUrl); + var descFilePath = await ParseSitePathAsync(destSite, relatedUrl); if (FileUtils.IsFileExists(sourceFilePath)) { FileUtils.MoveFile(sourceFilePath, descFilePath, false); diff --git a/src/SSCMS.Core/Services/PathManager.SiteFiles.cs b/src/SSCMS.Core/Services/PathManager.SiteFiles.cs deleted file mode 100644 index 1c776b5d5..000000000 --- a/src/SSCMS.Core/Services/PathManager.SiteFiles.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using SSCMS.Models; -using SSCMS.Utils; - -namespace SSCMS.Core.Services -{ - public partial class PathManager - { - public string GetSiteFilesPath(params string[] paths) - { - var path = PathUtils.Combine(_settingsManager.WebRootPath, DirectoryUtils.SiteFilesDirectoryName, PathUtils.Combine(paths)); - return path; - } - - public string GetSiteFilesUrl(params string[] paths) - { - return GetWebRootUrl(DirectoryUtils.SiteFilesDirectoryName, PageUtils.Combine(paths)); - } - - public string GetAdministratorUploadPath(int userId, params string[] paths) - { - var path = GetSiteFilesPath(DirectoryUtils.SiteFiles.Administrators, PathUtils.Combine(userId.ToString(), PathUtils.Combine(paths))); - return path; - } - - public string GetAdministratorUploadUrl(int userId, params string[] paths) - { - return GetWebRootUrl(DirectoryUtils.SiteFilesDirectoryName, DirectoryUtils.SiteFiles.Administrators, - PageUtils.Combine(userId.ToString(), PageUtils.Combine(paths))); - } - - public string GetUserUploadPath(int userId, params string[] paths) - { - var path = GetSiteFilesPath(DirectoryUtils.SiteFiles.Users, PathUtils.Combine(userId.ToString(), PathUtils.Combine(paths))); - return path; - } - - public string GetUserUploadUrl(int userId, params string[] paths) - { - return GetWebRootUrl(DirectoryUtils.SiteFilesDirectoryName, DirectoryUtils.SiteFiles.Users, - PageUtils.Combine(userId.ToString(), PageUtils.Combine(paths))); - } - - public string GetHomeUploadPath(params string[] paths) - { - var path = GetSiteFilesPath(DirectoryUtils.SiteFiles.Home, PathUtils.Combine(paths)); - return path; - } - - public string GetHomeUploadUrl(params string[] paths) - { - return GetSiteFilesUrl(PageUtils.Combine(DirectoryUtils.SiteFiles.Home, PageUtils.Combine(paths))); - } - - public string GetTemporaryFilesPath(params string[] paths) - { - var path = GetSiteFilesPath(DirectoryUtils.SiteFiles.TemporaryFiles, PathUtils.Combine(paths)); - return path; - } - - public string GetTemporaryFilesUrl(params string[] paths) - { - return GetSiteFilesUrl(PageUtils.Combine(DirectoryUtils.SiteFiles.TemporaryFiles, PageUtils.Combine(paths))); - } - - public string DefaultAvatarUrl => GetHomeUploadUrl("default_avatar.png"); - - public string GetUserUploadPath(int userId, string relatedPath) - { - return GetHomeUploadPath(userId.ToString(), relatedPath); - } - - public string GetUserUploadFileName(string filePath) - { - var dt = DateTime.Now; - return $"{dt.Day}{dt.Hour}{dt.Minute}{dt.Second}{dt.Millisecond}{PathUtils.GetExtension(filePath)}"; - } - - public string GetUserUploadUrl(int userId, string relatedUrl) - { - return GetHomeUploadUrl(userId.ToString(), relatedUrl); - } - - public string GetUserAvatarUrl(User user) - { - var imageUrl = user?.AvatarUrl; - - if (!string.IsNullOrEmpty(imageUrl)) - { - return PageUtils.IsProtocolUrl(imageUrl) ? imageUrl : GetUserUploadUrl(user.Id, imageUrl); - } - - return DefaultAvatarUrl; - } - } -} diff --git a/src/SSCMS.Core/Services/PathManager.Special.cs b/src/SSCMS.Core/Services/PathManager.Special.cs index 579321f95..2704af82f 100644 --- a/src/SSCMS.Core/Services/PathManager.Special.cs +++ b/src/SSCMS.Core/Services/PathManager.Special.cs @@ -16,8 +16,8 @@ public async Task GetSpecialUrlAsync(Site site, int specialId, bool isLo var specialUrl = await GetSpecialUrlAsync(site, specialId); var url = isLocal - ? GetLocalSpecialUrl(site.Id, specialId) - : await ParseNavigationUrlAsync(site, specialUrl, false); + ? GetPreviewSpecialUrl(site.Id, specialId) + : await ParseSiteUrlAsync(site, specialUrl, false); return RemoveDefaultFileName(site, url); } @@ -25,7 +25,7 @@ public async Task GetSpecialUrlAsync(Site site, int specialId, bool isLo public async Task GetSpecialDirectoryPathAsync(Site site, string url) { var virtualPath = PageUtils.RemoveFileNameFromUrl(url); - return await MapPathAsync(site, virtualPath); + return await ParseSitePathAsync(site, virtualPath); } private async Task GetSpecialUrlAsync(Site site, string url) @@ -35,7 +35,7 @@ private async Task GetSpecialUrlAsync(Site site, string url) { virtualPath = $"@/{StringUtils.TrimSlash(virtualPath)}"; } - return await ParseNavigationUrlAsync(site, virtualPath, false); + return await ParseSiteUrlAsync(site, virtualPath, false); } public async Task GetSpecialUrlAsync(Site site, int specialId) @@ -51,7 +51,7 @@ public string GetSpecialZipFilePath(string title, string directoryPath) public async Task GetSpecialZipFileUrlAsync(Site site, Special special) { - return await ParseNavigationUrlAsync(site, $"@/{special.Url}/{special.Title}.zip", true); + return await ParseSiteUrlAsync(site, $"@/{special.Url}/{special.Title}.zip", true); } public string GetSpecialSrcDirectoryPath(string directoryPath) @@ -114,7 +114,7 @@ private string GetSpecialContentByFilePath(string filePath) { try { - var content = _cacheManager.Get(CacheUtils.GetPathKey(filePath)); + var content = _cacheManager.Get(CacheUtils.GetPathKey(filePath)); if (content != null) return content; if (FileUtils.IsFileExists(filePath)) @@ -122,7 +122,7 @@ private string GetSpecialContentByFilePath(string filePath) content = FileUtils.ReadText(filePath, Encoding.UTF8); } - CacheUtils.SetFileContent(_cacheManager, content, filePath); + _cacheManager.AddOrUpdateFileWatcher(filePath, content); return content; } catch diff --git a/src/SSCMS.Core/Services/PathManager.TableStyle.cs b/src/SSCMS.Core/Services/PathManager.TableStyle.cs new file mode 100644 index 000000000..75f372573 --- /dev/null +++ b/src/SSCMS.Core/Services/PathManager.TableStyle.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using SSCMS.Core.Utils.Serialization; + +namespace SSCMS.Core.Services +{ + public partial class PathManager + { + public async Task ExportStylesAsync(int siteId, string tableName, List relatedIdentities) + { + return await ExportObject.ExportRootSingleTableStyleAsync(this, _databaseManager, siteId, tableName, + relatedIdentities); + } + + public async Task ImportStylesAsync(string tableName, List relatedIdentities, string zipFilePath) + { + return await ImportObject.ImportTableStyleByZipFileAsync(this, _databaseManager, tableName, relatedIdentities, + zipFilePath); + } + } +} diff --git a/src/SSCMS.Core/Services/PathManager.Template.cs b/src/SSCMS.Core/Services/PathManager.Template.cs index a52eb617a..5af355d5e 100644 --- a/src/SSCMS.Core/Services/PathManager.Template.cs +++ b/src/SSCMS.Core/Services/PathManager.Template.cs @@ -55,7 +55,7 @@ public async Task GetTemplateContentAsync(Site site, Template template) public async Task GetIncludeContentAsync(Site site, string file) { - var filePath = await MapPathAsync(site, AddVirtualToPath(file)); + var filePath = await ParseSitePathAsync(site, AddVirtualToPath(file)); return await GetContentByFilePathAsync(filePath); } @@ -63,7 +63,7 @@ public async Task GetContentByFilePathAsync(string filePath) { try { - var content = _cacheManager.Get(CacheUtils.GetPathKey(filePath)); + var content = _cacheManager.Get(CacheUtils.GetPathKey(filePath)); if (content != null) return content; if (FileUtils.IsFileExists(filePath)) @@ -71,7 +71,7 @@ public async Task GetContentByFilePathAsync(string filePath) content = await FileUtils.ReadTextAsync(filePath); } - CacheUtils.SetFileContent(_cacheManager, content, filePath); + _cacheManager.AddOrUpdateFileWatcher(filePath, content); return content; } catch diff --git a/src/SSCMS.Core/Services/PathManager.ZipImage.cs b/src/SSCMS.Core/Services/PathManager.ZipImage.cs new file mode 100644 index 000000000..c5f82ad0a --- /dev/null +++ b/src/SSCMS.Core/Services/PathManager.ZipImage.cs @@ -0,0 +1,95 @@ +using ICSharpCode.SharpZipLib.Zip; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Processing; +using SSCMS.Utils; + +namespace SSCMS.Core.Services +{ + public partial class PathManager + { + public void CreateZip(string zipFilePath, string directoryPath, string fileFilter = null) + { + var fz = new FastZip { CreateEmptyDirectories = true }; + fz.CreateZip(zipFilePath, directoryPath, true, fileFilter); + } + + public void ExtractZip(string zipFilePath, string directoryPath, string fileFilter = null) + { + var fz = new FastZip(); + fz.ExtractZip(zipFilePath, directoryPath, fileFilter); + } + + public (int width, int height) GetImageSize(string filePath) + { + using var image = Image.Load(filePath); + return (image.Width, image.Height); + } + + public void ResizeImage(string originalFilePath, string resizeFilePath, int width, int height) + { + // Open the file automatically detecting the file type to decode it. + // Our image is now in an uncompressed, file format agnostic, structure in-memory as + // a series of pixels. + using var image = Image.Load(originalFilePath); + // Resize the image in place and return it for chaining. + // 'x' signifies the current image processing context. + image.Mutate(x => x.Resize(width, height)); + + // The library automatically picks an encoder based on the file extension then + // encodes and write the data to disk. + // You can optionally set the encoder to choose. + image.Save(resizeFilePath); + } + + public void ResizeImageByMax(string originalFilePath, string resizeFilePath, int maxWidth, int maxHeight) + { + using var image = Image.Load(originalFilePath); + var (width, height) = (image.Width, image.Height); + + if (width > maxWidth && height > maxHeight) + { + int resizeWidth; + int resizeHeight; + if (width > height) + { + resizeWidth = maxWidth; + resizeHeight = (int)(height * (maxWidth / (double)width)); + + image.Mutate(x => x.Resize(resizeWidth, resizeHeight)); + image.Save(resizeFilePath); + } + else + { + resizeHeight = maxHeight; + resizeWidth = (int)(width * (maxHeight / (double)height)); + + image.Mutate(x => x.Resize(resizeWidth, resizeHeight)); + image.Save(resizeFilePath); + } + + image.Mutate(x => x.Resize(resizeWidth, resizeHeight)); + image.Save(resizeFilePath); + } + else if (width > maxWidth) + { + var resizeWidth = maxWidth; + var resizeHeight = (int)(height * (maxWidth / (double)width)); + + image.Mutate(x => x.Resize(resizeWidth, resizeHeight)); + image.Save(resizeFilePath); + } + else if (height > maxHeight) + { + var resizeHeight = maxHeight; + var resizeWidth = (int)(width * (maxHeight / (double)height)); + + image.Mutate(x => x.Resize(resizeWidth, resizeHeight)); + image.Save(resizeFilePath); + } + else + { + FileUtils.CopyFile(originalFilePath, resizeFilePath); + } + } + } +} diff --git a/src/SSCMS.Core/Services/PathManager.cs b/src/SSCMS.Core/Services/PathManager.cs index f9d6cdf72..e2d8d74e6 100644 --- a/src/SSCMS.Core/Services/PathManager.cs +++ b/src/SSCMS.Core/Services/PathManager.cs @@ -1,8 +1,8 @@ using System; using System.IO; using System.Threading.Tasks; -using CacheManager.Core; using Microsoft.AspNetCore.Http; +using SSCMS.Configuration; using SSCMS.Models; using SSCMS.Repositories; using SSCMS.Services; @@ -12,7 +12,7 @@ namespace SSCMS.Core.Services { public partial class PathManager : IPathManager { - private readonly ICacheManager _cacheManager; + private readonly ICacheManager _cacheManager; private readonly ISettingsManager _settingsManager; private readonly IDatabaseManager _databaseManager; private readonly ISpecialRepository _specialRepository; @@ -23,7 +23,7 @@ public partial class PathManager : IPathManager private readonly IContentRepository _contentRepository; private readonly ITableStyleRepository _tableStyleRepository; - public PathManager(ICacheManager cacheManager, ISettingsManager settingsManager, IDatabaseManager databaseManager, ISpecialRepository specialRepository, ITemplateLogRepository templateLogRepository, ITemplateRepository templateRepository, ISiteRepository siteRepository, IChannelRepository channelRepository, IContentRepository contentRepository, ITableStyleRepository tableStyleRepository) + public PathManager(ICacheManager cacheManager, ISettingsManager settingsManager, IDatabaseManager databaseManager, ISpecialRepository specialRepository, ITemplateLogRepository templateLogRepository, ITemplateRepository templateRepository, ISiteRepository siteRepository, IChannelRepository channelRepository, IContentRepository contentRepository, ITableStyleRepository tableStyleRepository) { _cacheManager = cacheManager; _settingsManager = settingsManager; @@ -70,29 +70,6 @@ public async Task GetAssetsUrlAsync(Site site) : PageUtils.Combine(await GetWebUrlAsync(site), site.AssetsDir); } - public string MapPath(string virtualPath) - { - virtualPath = PathUtils.RemovePathInvalidChar(virtualPath); - if (!string.IsNullOrEmpty(virtualPath)) - { - if (virtualPath.StartsWith("~")) - { - virtualPath = virtualPath.Substring(1); - } - virtualPath = PageUtils.Combine("~", virtualPath); - } - else - { - virtualPath = "~/"; - } - var rootPath = WebRootPath; - - virtualPath = !string.IsNullOrEmpty(virtualPath) ? virtualPath.Substring(2) : string.Empty; - var retVal = PathUtils.Combine(rootPath, virtualPath) ?? string.Empty; - - return retVal.Replace("/", "\\"); - } - public async Task UploadAsync(IFormFile file, string filePath) { DirectoryUtils.CreateDirectoryIfNotExists(filePath); diff --git a/src/SSCMS.Core/Services/PluginManager.Actions.cs b/src/SSCMS.Core/Services/PluginManager.Actions.cs index 709939caa..9e0c1ffd6 100644 --- a/src/SSCMS.Core/Services/PluginManager.Actions.cs +++ b/src/SSCMS.Core/Services/PluginManager.Actions.cs @@ -1,27 +1,20 @@ -using System.Threading.Tasks; +using ICSharpCode.SharpZipLib.Zip; using SSCMS.Core.Plugins; -using SSCMS.Core.Utils; -using SSCMS.Plugins; using SSCMS.Utils; namespace SSCMS.Core.Services { public partial class PluginManager { - public async Task DisableAsync(string pluginId, bool disabled) - { - var config = await GetConfigAsync(pluginId); - config[nameof(IPlugin.Disabled)] = disabled; - await SaveConfigAsync(pluginId, config); - } - public void Install(string pluginId, string version) { var packagesPath = PathUtils.Combine(_settingsManager.ContentRootPath, DirectoryUtils.Packages); var pluginPath = PathUtils.Combine(_directoryPath, pluginId); var zipFilePath = CloudUtils.Dl.DownloadPlugin(packagesPath, pluginId, version); - ZipUtils.ExtractZip(zipFilePath, pluginPath); + + var fz = new FastZip(); + fz.ExtractZip(zipFilePath, pluginPath, null); } public void UnInstall(string pluginId) diff --git a/src/SSCMS.Core/Services/PluginManager.Extensions.cs b/src/SSCMS.Core/Services/PluginManager.Extensions.cs deleted file mode 100644 index f6b2f807a..000000000 --- a/src/SSCMS.Core/Services/PluginManager.Extensions.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Microsoft.Extensions.Configuration; -using SSCMS.Configuration; -using Menu = SSCMS.Configuration.Menu; - -namespace SSCMS.Core.Services -{ - public partial class PluginManager - { - public SiteType GetSiteType(string key) - { - SiteType siteType = null; - var section = Configuration.GetSection($"extensions:siteTypes:{key}"); - if (section.Exists()) - { - siteType = section.Get(); - siteType.Id = key; - } - - return siteType ?? new SiteType - { - Id = AuthTypes.Resources.Site, - Text = "默认" - }; - } - - public List GetSiteTypes() - { - var siteTypes = new List(); - var section = Configuration.GetSection("extensions:siteTypes"); - if (!section.Exists()) return new List - { - new SiteType - { - Id = AuthTypes.Resources.Site, - Text = "默认" - } - }; - - //var children = section.GetChildren(); - //if (children != null) - //{ - // foreach (var child in children) - // { - // var siteType = child.Get(); - // siteTypes.Add(new SiteType - // { - // Id = child.Key, - // Text = siteType.Text, - // Order = siteType.Order - // }); - // } - //} - - //siteTypes = siteTypes.OrderBy(x => x.Order).ToList(); - - var list = section.Get>(); - foreach (var (key, value) in list) - { - siteTypes.Add(new SiteType - { - Id = key, - Text = value.Text, - Order = value.Order - }); - } - - return siteTypes.OrderByDescending(x => x.Order.HasValue).ThenBy(x => x.Order).ToList(); - } - - public List GetPermissions() - { - var permissions = new List(); - var section = Configuration.GetSection("extensions:permissions"); - if (!section.Exists()) return permissions; - - //var children = section.GetChildren(); - //if (children != null) - //{ - // foreach (var child in children) - // { - // var permission = child.Get(); - // permissions.Add(new Permission - // { - // Id = child.Key, - // Text = permission.Text, - // Type = permission.Type, - // Order = permission.Order - // }); - // } - //} - - var list = section.Get>(); - foreach (var (key, value) in list) - { - permissions.Add(new Permission - { - Id = key, - Text = value.Text, - Type = value.Type, - Order = value.Order - }); - } - - return permissions.OrderByDescending(x => x.Order.HasValue).ThenBy(x => x.Order).ToList(); - } - - public List GetMenus() - { - var section = Configuration.GetSection("extensions:menus"); - return GetMenus(section); - } - - private List GetMenus(IConfigurationSection section) - { - var menus = new List(); - if (section.Exists()) - { - var children = section.GetChildren(); - if (children != null) - { - foreach (var child in children) - { - var menu = child.Get(); - var childSection = child.GetSection("menus"); - - menus.Add(new Menu - { - Id = child.Key, - Text = menu.Text, - Type = menu.Type, - IconClass = menu.IconClass, - Link = menu.Link, - Target = menu.Target, - Permissions = menu.Permissions, - Order = menu.Order, - Children = GetMenus(childSection) - }); - } - } - } - - return menus.OrderByDescending(x => x.Order.HasValue).ThenBy(x => x.Order).ToList(); - } - - public List
GetTables() - { - var tables = new List
(); - var section = Configuration.GetSection("extensions:tables"); - if (!section.Exists()) return tables; - - var list = section.Get>(); - foreach (var (key, value) in list) - { - var table = value; - table.Id = key; - tables.Add(table); - } - - return tables; - } - } -} diff --git a/src/SSCMS.Core/Services/PluginManager.cs b/src/SSCMS.Core/Services/PluginManager.cs index 20d20f76e..d8f5c9b6e 100644 --- a/src/SSCMS.Core/Services/PluginManager.cs +++ b/src/SSCMS.Core/Services/PluginManager.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Reflection; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; +using SSCMS.Configuration; using SSCMS.Core.Plugins; using SSCMS.Plugins; using SSCMS.Services; @@ -23,35 +22,44 @@ public PluginManager(IConfiguration config, ISettingsManager settingsManager) _settingsManager = settingsManager; _directoryPath = PathUtils.Combine(settingsManager.ContentRootPath, Constants.PluginsDirectory); - DirectoryUtils.CreateDirectoryIfNotExists(_directoryPath); } public void Load() { + var plugins = new List(); Plugins = new List(); var configurations = new List { _config }; - foreach (var folderPath in Directory.GetDirectories(_directoryPath)) + if (!_settingsManager.IsDisablePlugins && DirectoryUtils.IsDirectoryExists(_directoryPath)) { - if (string.IsNullOrEmpty(folderPath)) continue; - var configPath = PathUtils.Combine(folderPath, Constants.PackageFileName); - if (!FileUtils.IsFileExists(configPath)) continue; + foreach (var folderPath in DirectoryUtils.GetDirectoryPaths(_directoryPath)) + { + if (string.IsNullOrEmpty(folderPath)) continue; + var configPath = PathUtils.Combine(folderPath, Constants.PackageFileName); + if (!FileUtils.IsFileExists(configPath)) continue; + + var plugin = new Plugin(folderPath, true); + if (!StringUtils.IsStrictName(plugin.Publisher) || !StringUtils.IsStrictName(plugin.Name)) continue; + if (PathUtils.GetFileName(folderPath) != plugin.PluginId) continue; - var plugin = new Plugin(folderPath, true); - if (!StringUtils.IsStrictName(plugin.Publisher) || !StringUtils.IsStrictName(plugin.Name)) continue; - if (Path.GetFileName(folderPath) != plugin.PluginId) continue; + plugins.Add(plugin); + + } - Plugins.Add(plugin); - if (!plugin.Disabled) + foreach (var plugin in plugins.OrderBy(x => x.Taxis == 0 ? int.MaxValue : x.Taxis)) { - var (success, errorMessage) = plugin.LoadAssembly(); - plugin.Success = success; - plugin.ErrorMessage = errorMessage; - if (success) + Plugins.Add(plugin); + if (!plugin.Disabled) { - configurations.Add(plugin.Configuration); + var (success, errorMessage) = plugin.LoadAssembly(); + plugin.Success = success; + plugin.ErrorMessage = errorMessage; + if (success) + { + configurations.Add(plugin.Configuration); + } } } } @@ -61,19 +69,17 @@ public void Load() { builder.AddConfiguration(configuration); } - Configuration = builder.Build(); + _settingsManager.Configuration = builder.Build(); } - public IPlugin Current - { - get - { - var assembly = Assembly.GetCallingAssembly(); - return assembly == null ? null : NetCorePlugins.FirstOrDefault(x => x.Assembly.FullName == assembly.FullName); - } - } - - public IConfiguration Configuration { get; private set; } + //public IPlugin Current + //{ + // get + // { + // var assembly = Assembly.GetCallingAssembly(); + // return assembly == null ? null : NetCorePlugins.FirstOrDefault(x => x.Assembly.FullName == assembly.FullName); + // } + //} public List Plugins { get; private set; } @@ -81,14 +87,52 @@ public IPlugin Current public List NetCorePlugins => EnabledPlugins.Where(x => x.Assembly != null).ToList(); + public List GetPlugins(int siteId) + { + return EnabledPlugins.Where(plugin => IsEnabled(plugin, siteId)).ToList(); + } + + public List GetPlugins(int siteId, int channelId) + { + var plugins = GetPlugins(siteId); + return plugins.Where(plugin => IsEnabled(plugin, siteId, channelId)).ToList(); + } + + private static bool IsEnabled(IPlugin plugin, int siteId) + { + if (plugin == null || plugin.Disabled) return false; + return plugin.ApplyToSites && (plugin.AllSites || ListUtils.Contains(plugin.SiteIds, siteId)); + } + + private static bool IsEnabled(IPlugin plugin, int siteId, int channelId) + { + if (!IsEnabled(plugin, siteId)) return false; + var siteConfig = plugin.SiteConfigs?.FirstOrDefault(x => x.SiteId == siteId); + if (siteConfig == null) return false; + return siteConfig.AllChannels || ListUtils.Contains(siteConfig.ChannelIds, channelId); + } + + public bool IsEnabled(string pluginId, int siteId) + { + var plugin = GetPlugin(pluginId); + return IsEnabled(plugin, siteId); + } + + public bool IsEnabled(string pluginId, int siteId, int channelId) + { + var plugin = GetPlugin(pluginId); + return IsEnabled(plugin, siteId, channelId); + } + public IPlugin GetPlugin(string pluginId) { return Plugins.FirstOrDefault(x => x.PluginId == pluginId); } - public IEnumerable GetExtensions(bool useCaching = false) where T : IPluginExtension + public IEnumerable GetExtensions(bool useCaching = true) where T : IPluginExtension { - return PluginUtils.GetInstances(NetCorePlugins, _settingsManager.ServiceProvider, useCaching); + var provider = _settingsManager.BuildServiceProvider(); + return PluginUtils.GetInstances(NetCorePlugins, provider, useCaching); } public async Task> GetConfigAsync(string pluginId) diff --git a/src/SSCMS.Core/Services/SettingsManager.Extensions.cs b/src/SSCMS.Core/Services/SettingsManager.Extensions.cs new file mode 100644 index 000000000..367ed6eb6 --- /dev/null +++ b/src/SSCMS.Core/Services/SettingsManager.Extensions.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.Configuration; +using SSCMS.Configuration; +using SSCMS.Utils; +using Menu = SSCMS.Configuration.Menu; + +namespace SSCMS.Core.Services +{ + public partial class SettingsManager + { + private static readonly SiteType DefaultSiteType = new SiteType + { + Id = Types.SiteTypes.Web, + IconClass = "ion-earth", + Text = "网站" + }; + + public SiteType GetSiteType(string key) + { + SiteType siteType = null; + var section = Configuration.GetSection($"extensions:siteTypes:{key}"); + if (section.Exists()) + { + siteType = section.Get(); + siteType.Id = key; + } + + return siteType ?? DefaultSiteType; + } + + public List GetSiteTypes() + { + var siteTypes = new List(); + var section = Configuration.GetSection("extensions:siteTypes"); + if (!section.Exists()) return new List + { + DefaultSiteType + }; + + //var children = section.GetChildren(); + //if (children != null) + //{ + // foreach (var child in children) + // { + // var siteType = child.Get(); + // siteTypes.Add(new SiteType + // { + // Id = child.Key, + // Text = siteType.Text, + // Order = siteType.Order + // }); + // } + //} + + //siteTypes = siteTypes.OrderBy(x => x.Order).ToList(); + + var list = section.Get>(); + foreach (var (key, value) in list) + { + siteTypes.Add(new SiteType + { + Id = key, + Text = value.Text, + Order = value.Order + }); + } + + return siteTypes.OrderByDescending(x => x.Order.HasValue).ThenBy(x => x.Order).ToList(); + } + + public List GetPermissions() + { + var permissions = new List(); + var section = Configuration.GetSection("extensions:permissions"); + if (!section.Exists()) return permissions; + + //var children = section.GetChildren(); + //if (children != null) + //{ + // foreach (var child in children) + // { + // var permission = child.Get(); + // permissions.Add(new Permission + // { + // Id = child.Key, + // Text = permission.Text, + // Type = permission.Type, + // Order = permission.Order + // }); + // } + //} + + var list = section.Get>(); + foreach (var (key, value) in list) + { + permissions.Add(new Permission + { + Id = key, + Text = value.Text, + Type = value.Type, + Order = value.Order + }); + } + + return permissions.OrderByDescending(x => x.Order.HasValue).ThenBy(x => x.Order).ToList(); + } + + public List GetMenus() + { + var section = Configuration.GetSection("extensions:menus"); + return GetMenus(section); + } + + private List GetMenus(IConfigurationSection section) + { + var menus = new List(); + if (section.Exists()) + { + var children = section.GetChildren(); + if (children != null) + { + foreach (var child in children) + { + var menu = child.Get(); + var childSection = child.GetSection("menus"); + + menus.Add(new Menu + { + Id = child.Key, + Text = menu.Text, + Type = menu.Type, + IconClass = menu.IconClass, + Link = menu.Link, + Target = menu.Target, + Permissions = menu.Permissions, + Order = menu.Order, + Children = GetMenus(childSection) + }); + } + } + } + + return menus.OrderByDescending(x => x.Order.HasValue).ThenBy(x => x.Order).ToList(); + } + + public List
GetTables() + { + var tables = new List
(); + var section = Configuration.GetSection("extensions:tables"); + if (!section.Exists()) return tables; + + var list = section.Get>(); + foreach (var (key, value) in list) + { + var table = value; + table.Id = key; + tables.Add(table); + } + + return tables; + } + + public List GetContentTableNames() + { + var tables = GetTables(); + return tables + .Where(x => StringUtils.EqualsIgnoreCase(x.Type, Types.TableTypes.Content)).Select(x => x.Id) + .ToList(); + } + } +} diff --git a/src/SSCMS.Core/Services/SettingsManager.cs b/src/SSCMS.Core/Services/SettingsManager.cs index 04fc1462a..078e31bc5 100644 --- a/src/SSCMS.Core/Services/SettingsManager.cs +++ b/src/SSCMS.Core/Services/SettingsManager.cs @@ -1,7 +1,7 @@ using System; -using System.Linq; +using System.Collections.Generic; using System.Reflection; -using System.Runtime.Versioning; +using System.Runtime.InteropServices; using Datory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -11,7 +11,7 @@ namespace SSCMS.Core.Services { - public class SettingsManager : ISettingsManager + public partial class SettingsManager : ISettingsManager { private readonly IServiceCollection _services; private readonly IConfiguration _config; @@ -27,31 +27,63 @@ public SettingsManager(IServiceCollection services, IConfiguration config, strin { Version = entryAssembly.GetCustomAttribute() .InformationalVersion; - - if (entryAssembly - .GetCustomAttributes(typeof(TargetFrameworkAttribute), false) - .SingleOrDefault() is TargetFrameworkAttribute targetFrameworkAttribute) + FrameworkDescription = RuntimeInformation.FrameworkDescription; + OSDescription = RuntimeInformation.OSDescription; + string os; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + os = "win"; + } + else if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + os = "osx"; + } + else + { + os = "linux"; + } + var architecture = "x64"; + if (RuntimeInformation.OSArchitecture == Architecture.Arm || + RuntimeInformation.OSArchitecture == Architecture.X86) { - TargetFramework = targetFrameworkAttribute.FrameworkName; + architecture = "x86"; } + OSArchitecture = $"{os}-{architecture}"; + Containerized = Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") != null; + CPUCores = Environment.ProcessorCount; } } - public IServiceProvider ServiceProvider => _services.BuildServiceProvider(); + public IServiceProvider BuildServiceProvider() + { + return _services.BuildServiceProvider(); + } + public IConfiguration Configuration { get; set; } public string ContentRootPath { get; } public string WebRootPath { get; } public string Version { get; } - public string TargetFramework { get; } - public bool IsNightlyUpdate => _config.GetValue(nameof(IsNightlyUpdate), false); + public string FrameworkDescription { get; } + public string OSArchitecture { get; set; } + public string OSDescription { get; } + public bool Containerized { get; } + public int CPUCores { get; } public bool IsProtectData => _config.GetValue(nameof(IsProtectData), false); + public bool IsDisablePlugins => _config.GetValue(nameof(IsDisablePlugins), false); public string SecurityKey => _config.GetValue(nameof(SecurityKey)); + public string ApiHost => _config.GetValue(nameof(ApiHost), "/"); public DatabaseType DatabaseType => TranslateUtils.ToEnum(IsProtectData ? Decrypt(_config.GetValue("Database:Type")) : _config.GetValue("Database:Type"), DatabaseType.MySql); public string DatabaseConnectionString => IsProtectData ? Decrypt(_config.GetValue("Database:ConnectionString")) : _config.GetValue("Database:ConnectionString"); public IDatabase Database => new Database(DatabaseType, DatabaseConnectionString); public string RedisConnectionString => IsProtectData ? Decrypt(_config.GetValue("Redis:ConnectionString")) : _config.GetValue("Redis:ConnectionString"); public IRedis Redis => new Redis(RedisConnectionString); + public string AdminRestrictionHost => _config.GetValue("AdminRestriction:Host"); + + public string[] AdminRestrictionAllowList => _config.GetSection("AdminRestriction:AllowList").Get(); + + public string[] AdminRestrictionBlockList => _config.GetSection("AdminRestriction:BlockList").Get(); + public string Encrypt(string inputString, string securityKey = null) { return TranslateUtils.EncryptStringBySecretKey(inputString, !string.IsNullOrEmpty(securityKey) ? securityKey : SecurityKey); @@ -62,8 +94,7 @@ public string Decrypt(string inputString, string securityKey = null) return TranslateUtils.DecryptStringBySecretKey(inputString, !string.IsNullOrEmpty(securityKey) ? securityKey : SecurityKey); } - public void SaveSettings(bool isNightlyUpdate, bool isProtectData, DatabaseType databaseType, - string databaseConnectionString, string redisConnectionString) + public void SaveSettings(bool isProtectData, bool isDisablePlugins, DatabaseType databaseType, string databaseConnectionString, string redisConnectionString, string adminRestrictionHost, string[] adminRestrictionAllowList, string[] adminRestrictionBlockList) { var type = databaseType.GetValue(); var databaseConnectionStringValue = databaseConnectionString; @@ -75,24 +106,7 @@ public void SaveSettings(bool isNightlyUpdate, bool isProtectData, DatabaseType redisConnectionStringValue = Encrypt(redisConnectionString, SecurityKey); } -// var json = $@" -//{{ -// ""IsNightlyUpdate"": {isNightlyUpdate.ToString().ToLower()}, -// ""IsProtectData"": {isProtectData.ToString().ToLower()}, -// ""SecurityKey"": ""{SecurityKey}"", -// ""Database"": {{ -// ""Type"": ""{type}"", -// ""ConnectionString"": ""{databaseConnectionStringValue}"" -// }}, -// ""Redis"": {{ -// ""ConnectionString"": ""{redisConnectionStringValue}"" -// }} -//}}"; - -// await FileUtils.WriteTextAsync(path, json.Trim()); - - InstallUtils.SaveSettings(ContentRootPath, isNightlyUpdate, isProtectData, SecurityKey, type, - databaseConnectionStringValue, redisConnectionStringValue); + InstallUtils.SaveSettings(ContentRootPath, isProtectData, isDisablePlugins, SecurityKey, type, databaseConnectionStringValue, redisConnectionStringValue, adminRestrictionHost, adminRestrictionAllowList, adminRestrictionBlockList); } } } diff --git a/src/SSCMS.Core/Services/TaskManager.cs b/src/SSCMS.Core/Services/TaskManager.cs index d19ccdd6c..8faa4b8d8 100644 --- a/src/SSCMS.Core/Services/TaskManager.cs +++ b/src/SSCMS.Core/Services/TaskManager.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; +using FluentScheduler; using SSCMS.Services; namespace SSCMS.Core.Services @@ -31,5 +32,10 @@ public async Task> DequeueAsync( return workItem; } + + public void RunOnceAt(Action job, DateTime dateTime) + { + JobManager.AddJob(job, s => s.ToRunOnceAt(dateTime)); + } } } diff --git a/src/SSCMS.Core/Services/WxManager.Reply.cs b/src/SSCMS.Core/Services/WxManager.Reply.cs new file mode 100644 index 000000000..7bc3d89c1 --- /dev/null +++ b/src/SSCMS.Core/Services/WxManager.Reply.cs @@ -0,0 +1,141 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using SSCMS.Enums; +using SSCMS.Models; +using SSCMS.Utils; + +namespace SSCMS.Core.Services +{ + ////群发媒体文件时传入mediaId,群发文本消息时传入content,群发卡券时传入cardId + public partial class WxManager + { + private static bool IsMatch(WxReplyKeyword keyword, string content) + { + if (keyword.Exact) + { + return StringUtils.EqualsIgnoreCase(keyword.Text, content); + } + + return StringUtils.ContainsIgnoreCase(keyword.Text, content) || + StringUtils.ContainsIgnoreCase(content, keyword.Text); + } + + public async Task> GetMessagesAsync(int siteId, string content, int defaultMessageId) + { + List messages = null; + + var keywords = await _wxReplyKeywordRepository.GetKeywordsAsync(siteId); + var keyword = keywords.FirstOrDefault(x => IsMatch(x, content)); + if (keyword != null) + { + var rule = await _wxReplyRuleRepository.GetAsync(keyword.RuleId); + if (rule != null) + { + var allMessages = await GetMessagesAsync(siteId, keyword.RuleId); + if (rule.Random) + { + var index = StringUtils.GetRandomInt(0, allMessages.Count - 1); + messages = new List + { + allMessages[index] + }; + } + else + { + messages = allMessages; + } + } + } + else if (defaultMessageId > 0) + { + var message = await GetMessageAsync(siteId, defaultMessageId); + if (message != null) + { + messages = new List + { + message + }; + } + } + + return messages; + } + + public async Task> GetMessagesAsync(int siteId, int ruleId) + { + var messages = new List(); + var dbMessages = await _wxReplyMessageRepository.GetMessagesAsync(siteId, ruleId); + + foreach (var dbMessage in dbMessages) + { + var message = await GetMessageAsync(dbMessage); + if (message != null) + { + messages.Add(message); + } + } + + return messages; + } + + public async Task GetMessageAsync(int siteId, int messageId) + { + if (siteId == 0 || messageId == 0) return null; + + var dbMessage = await _wxReplyMessageRepository.GetMessageAsync(siteId, messageId); + + return await GetMessageAsync(dbMessage); + } + + private async Task GetMessageAsync(WxReplyMessage message) + { + if (message.MaterialType == MaterialType.Message) + { + var material = await _materialMessageRepository.GetAsync(message.MaterialId); + if (material != null) + { + message.MediaId = material.MediaId; + message.Items = material.Items; + return message; + } + } + else if (message.MaterialType == MaterialType.Image) + { + var material = await _materialImageRepository.GetAsync(message.MaterialId); + if (material != null) + { + message.MediaId = material.MediaId; + message.Image = material; + return message; + } + } + else if (message.MaterialType == MaterialType.Audio) + { + var material = await _materialAudioRepository.GetAsync(message.MaterialId); + if (material != null) + { + message.MediaId = material.MediaId; + message.Audio = material; + return message; + } + } + else if (message.MaterialType == MaterialType.Video) + { + var material = await _materialVideoRepository.GetAsync(message.MaterialId); + if (material != null) + { + message.MediaId = material.MediaId; + message.Video = material; + return message; + } + } + else if (message.MaterialType == MaterialType.Text) + { + return message; + } + + return null; + } + } +} diff --git a/src/SSCMS.Core/Services/WxManager.Send.cs b/src/SSCMS.Core/Services/WxManager.Send.cs new file mode 100644 index 000000000..74dea9c7c --- /dev/null +++ b/src/SSCMS.Core/Services/WxManager.Send.cs @@ -0,0 +1,160 @@ +using System; +using System.Threading.Tasks; +using Datory; +using Senparc.Weixin.MP.AdvancedAPIs; +using SSCMS.Enums; +using SSCMS.Models; +using SSCMS.Utils; + +namespace SSCMS.Core.Services +{ + ////群发媒体文件时传入mediaId,群发文本消息时传入content,群发卡券时传入cardId + public partial class WxManager + { + public async Task PreviewSendAsync(string accessTokenOrAppId, MaterialType materialType, string value, string wxName) + { + if (string.IsNullOrEmpty(value) || string.IsNullOrWhiteSpace(wxName)) return; + + await GroupMessageApi.SendGroupMessagePreviewAsync(accessTokenOrAppId, GetGroupMessageType(materialType), value, + null, StringUtils.Trim(wxName)); + } + + public async Task MassSendAsync(string accessTokenOrAppId, MaterialType materialType, string value, bool isToAll, string tagId, DateTime? runOnceAt) + { + if (runOnceAt.HasValue) + { + _taskManager.RunOnceAt(async () => + { + await GroupMessageApi.SendGroupMessageByTagIdAsync(accessTokenOrAppId, tagId, value, + GetGroupMessageType(materialType), isToAll); + }, runOnceAt.Value); + } + else + { + await GroupMessageApi.SendGroupMessageByTagIdAsync(accessTokenOrAppId, tagId, value, + GetGroupMessageType(materialType), isToAll); + } + } + + public async Task CustomSendAsync(string accessTokenOrAppId, string openId, WxReplyMessage message) + { + if (message.MaterialType == MaterialType.Message) + { + await CustomSendMessageAsync(accessTokenOrAppId, openId, message.SiteId, message.MaterialId, message.MediaId); + } + else if (message.MaterialType == MaterialType.Text) + { + await CustomSendTextAsync(accessTokenOrAppId, openId, message.SiteId, message.Text); + } + else if (message.MaterialType == MaterialType.Image) + { + await CustomSendImageAsync(accessTokenOrAppId, openId, message.SiteId, message.MaterialId, message.MediaId); + } + else if (message.MaterialType == MaterialType.Audio) + { + await CustomSendAudioAsync(accessTokenOrAppId, openId, message.SiteId, message.MaterialId, message.MediaId); + } + else if (message.MaterialType == MaterialType.Video) + { + await CustomSendVideoAsync(accessTokenOrAppId, openId, message.SiteId, message.MaterialId, message.MediaId); + } + } + + public async Task CustomSendTextAsync(string accessTokenOrAppId, string openId, int siteId, string text) + { + await _wxChatRepository.ReplyAdd(new WxChat + { + SiteId = siteId, + OpenId = openId, + IsReply = true, + MaterialType = MaterialType.Text, + MaterialId = 0, + Text = text + }); + + await CustomApi.SendTextAsync(accessTokenOrAppId, openId, text); + } + + public async Task CustomSendMessageAsync(string accessTokenOrAppId, string openId, int siteId, int materialId, string mediaId) + { + if (string.IsNullOrEmpty(mediaId)) + { + mediaId = await PushMaterialAsync(accessTokenOrAppId, MaterialType.Message, materialId); + } + + await _wxChatRepository.ReplyAdd(new WxChat + { + SiteId = siteId, + OpenId = openId, + IsReply = true, + MaterialType = MaterialType.Message, + MaterialId = materialId, + Text = MaterialType.Message.GetDisplayName() + }); + + await CustomApi.SendMpNewsAsync(accessTokenOrAppId, openId, mediaId); + } + + public async Task CustomSendImageAsync(string accessTokenOrAppId, string openId, int siteId, int materialId, string mediaId) + { + if (string.IsNullOrEmpty(mediaId)) + { + mediaId = await PushMaterialAsync(accessTokenOrAppId, MaterialType.Image, materialId); + } + + await _wxChatRepository.ReplyAdd(new WxChat + { + SiteId = siteId, + OpenId = openId, + IsReply = true, + MaterialType = MaterialType.Image, + MaterialId = materialId, + Text = MaterialType.Image.GetDisplayName() + }); + + await CustomApi.SendImageAsync(accessTokenOrAppId, openId, mediaId); + } + + public async Task CustomSendAudioAsync(string accessTokenOrAppId, string openId, int siteId, int materialId, string mediaId) + { + if (string.IsNullOrEmpty(mediaId)) + { + mediaId = await PushMaterialAsync(accessTokenOrAppId, MaterialType.Audio, materialId); + } + + await _wxChatRepository.ReplyAdd(new WxChat + { + SiteId = siteId, + OpenId = openId, + IsReply = true, + MaterialType = MaterialType.Audio, + MaterialId = materialId, + Text = MaterialType.Audio.GetDisplayName() + }); + + await CustomApi.SendVoiceAsync(accessTokenOrAppId, openId, mediaId); + } + + public async Task CustomSendVideoAsync(string accessTokenOrAppId, string openId, int siteId, int materialId, string mediaId) + { + if (string.IsNullOrEmpty(mediaId)) + { + mediaId = await PushMaterialAsync(accessTokenOrAppId, MaterialType.Video, materialId); + } + + var video = await _materialVideoRepository.GetAsync(materialId); + + await _wxChatRepository.ReplyAdd(new WxChat + { + SiteId = siteId, + OpenId = openId, + IsReply = true, + MaterialType = MaterialType.Video, + MaterialId = materialId, + Text = MaterialType.Video.GetDisplayName() + }); + + await CustomApi.SendVideoAsync(accessTokenOrAppId, openId, mediaId, video.Title, video.Description); + } + } +} diff --git a/src/SSCMS.Core/Services/WxManager.Sync.cs b/src/SSCMS.Core/Services/WxManager.Sync.cs new file mode 100644 index 000000000..75cfa340c --- /dev/null +++ b/src/SSCMS.Core/Services/WxManager.Sync.cs @@ -0,0 +1,421 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Datory; +using Senparc.CO2NET.Extensions; +using Senparc.Weixin.MP; +using Senparc.Weixin.MP.AdvancedAPIs; +using Senparc.Weixin.MP.AdvancedAPIs.GroupMessage; +using Senparc.Weixin.MP.CommonAPIs; +using Senparc.Weixin.MP.Entities.Menu; +using SSCMS.Core.Utils; +using SSCMS.Enums; +using SSCMS.Models; +using SSCMS.Utils; + +namespace SSCMS.Core.Services +{ + public partial class WxManager + { + public async Task PullMaterialAsync(string accessTokenOrAppId, MaterialType materialType, int groupId) + { + var count = await MediaApi.GetMediaCountAsync(accessTokenOrAppId); + if (materialType == MaterialType.Message) + { + if (count.news_count > 0) + { + var newsList = await MediaApi.GetNewsMediaListAsync(accessTokenOrAppId, 0, count.news_count); + newsList.item.Reverse(); + + foreach (var message in newsList.item) + { + if (await _materialMessageRepository.IsExistsAsync(message.media_id)) continue; + + //var news = await MediaApi.GetForeverNewsAsync(accessTokenOrAppId, message.media_id); + var messageItems = new List(); + foreach (var item in message.content.news_item) + { + var imageUrl = string.Empty; + if (!string.IsNullOrEmpty(item.thumb_media_id) && !string.IsNullOrEmpty(item.thumb_url)) + { + await using var ms = new MemoryStream(); + await MediaApi.GetForeverMediaAsync(accessTokenOrAppId, item.thumb_media_id, ms); + ms.Seek(0, SeekOrigin.Begin); + + var extName = "png"; + if (StringUtils.Contains(item.thumb_url, "wx_fmt=")) + { + extName = item.thumb_url.Substring(item.thumb_url.LastIndexOf("=", StringComparison.Ordinal) + 1); + } + + var materialFileName = PathUtils.GetMaterialFileNameByExtName(extName); + var virtualDirectoryPath = PathUtils.GetMaterialVirtualDirectoryPath(UploadType.Image); + + var directoryPath = PathUtils.Combine(_settingsManager.WebRootPath, virtualDirectoryPath); + var filePath = PathUtils.Combine(directoryPath, materialFileName); + + await FileUtils.WriteStreamAsync(filePath, ms); + + imageUrl = PageUtils.Combine(virtualDirectoryPath, materialFileName); + } + else if (!string.IsNullOrEmpty(item.thumb_url)) + { + var extName = "png"; + if (StringUtils.Contains(item.thumb_url, "wx_fmt=")) + { + extName = item.thumb_url.Substring(item.thumb_url.LastIndexOf("=", StringComparison.Ordinal) + 1); + } + + var materialFileName = PathUtils.GetMaterialFileNameByExtName(extName); + var virtualDirectoryPath = PathUtils.GetMaterialVirtualDirectoryPath(UploadType.Image); + + var directoryPath = PathUtils.Combine(_settingsManager.WebRootPath, virtualDirectoryPath); + var filePath = PathUtils.Combine(directoryPath, materialFileName); + + WebClientUtils.Download(item.thumb_url, filePath); + + imageUrl = PageUtils.Combine(virtualDirectoryPath, materialFileName); + } + + var commentType = CommentType.Block; + if (item.need_open_comment == 1) + { + commentType = item.only_fans_can_comment == 1 ? CommentType.OnlyFans : CommentType.Everyone; + } + + messageItems.Add(new MaterialMessageItem + { + MessageId = 0, + MaterialType = MaterialType.Article, + MaterialId = 0, + Taxis = 0, + ThumbMediaId = item.thumb_media_id, + Author = item.author, + Title = item.title, + ContentSourceUrl = item.content_source_url, + Content = SaveImages(item.content), + Digest = item.digest, + ShowCoverPic = item.show_cover_pic == "1", + ThumbUrl = imageUrl, + Url = item.url, + CommentType = commentType + }); + } + + await _materialMessageRepository.InsertAsync(groupId, message.media_id, messageItems); + } + } + } + else if (materialType == MaterialType.Image) + { + if (count.image_count > 0) + { + var list = await MediaApi.GetOthersMediaListAsync(accessTokenOrAppId, UploadMediaFileType.image, 0, count.image_count); + + foreach (var image in list.item) + { + if (await _materialImageRepository.IsExistsAsync(image.media_id)) continue; + + await using var ms = new MemoryStream(); + await MediaApi.GetForeverMediaAsync(accessTokenOrAppId, image.media_id, ms); + ms.Seek(0, SeekOrigin.Begin); + + var extName = image.url.Substring(image.url.LastIndexOf("=", StringComparison.Ordinal) + 1); + + var materialFileName = PathUtils.GetMaterialFileNameByExtName(extName); + var virtualDirectoryPath = PathUtils.GetMaterialVirtualDirectoryPath(UploadType.Image); + + var directoryPath = PathUtils.Combine(_settingsManager.WebRootPath, virtualDirectoryPath); + var filePath = PathUtils.Combine(directoryPath, materialFileName); + + await FileUtils.WriteStreamAsync(filePath, ms); + + var material = new MaterialImage + { + GroupId = groupId, + Title = image.name, + Url = PageUtils.Combine(virtualDirectoryPath, materialFileName), + MediaId = image.media_id + }; + + await _materialImageRepository.InsertAsync(material); + } + } + } + else if (materialType == MaterialType.Audio) + { + if (count.voice_count > 0) + { + var list = await MediaApi.GetOthersMediaListAsync(accessTokenOrAppId, UploadMediaFileType.voice, 0, count.voice_count); + + foreach (var voice in list.item) + { + if (await _materialAudioRepository.IsExistsAsync(voice.media_id)) continue; + + await using var ms = new MemoryStream(); + await MediaApi.GetForeverMediaAsync(accessTokenOrAppId, voice.media_id, ms); + ms.Seek(0, SeekOrigin.Begin); + + var extName = voice.url.Substring(voice.url.LastIndexOf("=", StringComparison.Ordinal) + 1); + + var materialFileName = PathUtils.GetMaterialFileNameByExtName(extName); + var virtualDirectoryPath = PathUtils.GetMaterialVirtualDirectoryPath(UploadType.Audio); + + var directoryPath = PathUtils.Combine(_settingsManager.WebRootPath, virtualDirectoryPath); + var filePath = PathUtils.Combine(directoryPath, materialFileName); + + await FileUtils.WriteStreamAsync(filePath, ms); + + var audio = new MaterialAudio + { + GroupId = groupId, + Title = voice.name, + FileType = extName.ToUpper().Replace(".", string.Empty), + Url = PageUtils.Combine(virtualDirectoryPath, materialFileName), + MediaId = voice.media_id + }; + + await _materialAudioRepository.InsertAsync(audio); + } + } + } + else if (materialType == MaterialType.Video) + { + if (count.video_count > 0) + { + var list = await MediaApi.GetOthersMediaListAsync(accessTokenOrAppId, UploadMediaFileType.video, 0, count.video_count); + + foreach (var video in list.item) + { + if (await _materialVideoRepository.IsExistsAsync(video.media_id)) continue; + + await using var ms = new MemoryStream(); + await MediaApi.GetForeverMediaAsync(accessTokenOrAppId, video.media_id, ms); + ms.Seek(0, SeekOrigin.Begin); + + var extName = video.url.Substring(video.url.LastIndexOf("=", StringComparison.Ordinal) + 1); + + var materialFileName = PathUtils.GetMaterialFileNameByExtName(extName); + var virtualDirectoryPath = PathUtils.GetMaterialVirtualDirectoryPath(UploadType.Video); + + var directoryPath = PathUtils.Combine(_settingsManager.WebRootPath, virtualDirectoryPath); + var filePath = PathUtils.Combine(directoryPath, materialFileName); + + await FileUtils.WriteStreamAsync(filePath, ms); + + var material = new MaterialVideo + { + GroupId = groupId, + Title = video.name, + FileType = extName.ToUpper().Replace(".", string.Empty), + Url = PageUtils.Combine(virtualDirectoryPath, materialFileName), + MediaId = video.media_id + }; + + await _materialVideoRepository.InsertAsync(material); + } + } + } + } + + public async Task PushMaterialAsync(string accessTokenOrAppId, MaterialType materialType, int materialId) + { + string mediaId = null; + + if (materialType == MaterialType.Message) + { + var message = await _materialMessageRepository.GetAsync(materialId); + + var newsList = new List(); + foreach (var item in message.Items) + { + var news = new NewsModel + { + thumb_media_id = item.ThumbMediaId, + author = item.Author, + title = item.Title, + content_source_url = item.ContentSourceUrl, + content = item.Content, + digest = item.Digest, + show_cover_pic = item.ShowCoverPic ? "1" : "0", + thumb_url = item.ThumbUrl, + need_open_comment = item.CommentType == CommentType.Block ? 0 : 1, + only_fans_can_comment = item.CommentType == CommentType.OnlyFans ? 1 : 0 + }; + newsList.Add(news); + } + + mediaId = message.MediaId; + if (string.IsNullOrEmpty(mediaId)) + { + var result = await MediaApi.UploadNewsAsync(accessTokenOrAppId, 10000, newsList.ToArray()); + mediaId = result.media_id; + await _materialMessageRepository.UpdateMediaIdAsync(materialId, mediaId); + } + else + { + var index = 0; + foreach (var news in newsList) + { + await MediaApi.UpdateForeverNewsAsync(accessTokenOrAppId, message.MediaId, index++, news); + } + } + + // sync article url + var media = await MediaApi.GetForeverNewsAsync(accessTokenOrAppId, mediaId); + for (var i = 0; i < message.Items.Count; i++) + { + var item = media.news_item[i]; + await _materialArticleRepository.UpdateUrlAsync(message.Items[i].MaterialId, item.url); + } + } + else if (materialType == MaterialType.Image) + { + var image = await _materialImageRepository.GetAsync(materialId); + mediaId = image.MediaId; + if (string.IsNullOrEmpty(mediaId)) + { + var filePath = _pathManager.ParsePath(image.Url); + if (FileUtils.IsFileExists(filePath)) + { + var result = await MediaApi.UploadForeverMediaAsync(accessTokenOrAppId, filePath); + mediaId = result.media_id; + await _materialImageRepository.UpdateMediaIdAsync(materialId, mediaId); + } + } + } + else if (materialType == MaterialType.Audio) + { + var audio = await _materialAudioRepository.GetAsync(materialId); + mediaId = audio.MediaId; + if (string.IsNullOrEmpty(mediaId)) + { + var filePath = _pathManager.ParsePath(audio.Url); + if (FileUtils.IsFileExists(filePath)) + { + var result = await MediaApi.UploadForeverMediaAsync(accessTokenOrAppId, filePath); + mediaId = result.media_id; + await _materialAudioRepository.UpdateMediaIdAsync(materialId, mediaId); + } + } + } + else if (materialType == MaterialType.Video) + { + var video = await _materialVideoRepository.GetAsync(materialId); + mediaId = video.MediaId; + if (string.IsNullOrEmpty(mediaId)) + { + var filePath = _pathManager.ParsePath(video.Url); + if (FileUtils.IsFileExists(filePath)) + { + var result = await MediaApi.UploadForeverMediaAsync(accessTokenOrAppId, filePath); + mediaId = result.media_id; + await _materialVideoRepository.UpdateMediaIdAsync(materialId, mediaId); + } + } + } + + return mediaId; + } + + public async Task PullMenuAsync(string accessTokenOrAppId, int siteId) + { + var result = CommonApi.GetMenu(accessTokenOrAppId); + + if (result == null) return; + + await _wxMenuRepository.DeleteAllAsync(siteId); + + var json = result.menu.button.ToJson(); + var buttons = TranslateUtils.JsonDeserialize>(json); + + var firstTaxis = 1; + foreach (var button in buttons) + { + + var first = new WxMenu + { + SiteId = siteId, + ParentId = 0, + Taxis = firstTaxis++, + Text = button.name, + MenuType = TranslateUtils.ToEnum(button.type, WxMenuType.View), + Key = button.key, + Url = button.url, + AppId = button.appid, + PagePath = button.pagepath, + MediaId = button.media_id + }; + var menuId = await _wxMenuRepository.InsertAsync(first); + if (button.sub_button != null && button.sub_button.Count > 0) + { + var childTaxis = 1; + foreach (var sub in button.sub_button) + { + var child = new WxMenu + { + SiteId = siteId, + ParentId = menuId, + Taxis = childTaxis++, + Text = sub.name, + MenuType = TranslateUtils.ToEnum(sub.type, WxMenuType.View), + Key = sub.key, + Url = sub.url, + AppId = sub.appid, + PagePath = sub.pagepath, + MediaId = sub.media_id + }; + await _wxMenuRepository.InsertAsync(child); + } + } + } + } + + public async Task PushMenuAsync(string accessTokenOrAppId, int siteId) + { + var resultFull = new GetMenuResultFull + { + menu = new MenuFull_ButtonGroup + { + button = new List() + } + }; + + var openMenus = await _wxMenuRepository.GetMenusAsync(siteId); + + foreach (var firstMenu in openMenus.Where(x => x.ParentId == 0)) + { + var root = new MenuFull_RootButton + { + name = firstMenu.Text, + type = firstMenu.MenuType.GetValue(), + url = firstMenu.Url, + key = firstMenu.Key, + sub_button = new List() + }; + foreach (var child in openMenus.Where(x => x.ParentId == firstMenu.Id)) + { + root.sub_button.Add(new MenuFull_RootButton + { + name = child.Text, + type = child.MenuType.GetValue(), + url = child.Url, + key = child.Key + }); + } + + resultFull.menu.button.Add(root); + } + + var buttonGroup = CommonApi.GetMenuFromJsonResult(resultFull, new ButtonGroup()).menu; + var result = CommonApi.CreateMenu(accessTokenOrAppId, buttonGroup); + + if (result.errmsg != "ok") + { + throw new Exception(result.errmsg); + } + } + } +} diff --git a/src/SSCMS.Core/Services/WxManager.User.cs b/src/SSCMS.Core/Services/WxManager.User.cs new file mode 100644 index 000000000..3edf36721 --- /dev/null +++ b/src/SSCMS.Core/Services/WxManager.User.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Senparc.Weixin; +using Senparc.Weixin.MP.AdvancedAPIs; +using Senparc.Weixin.MP.AdvancedAPIs.User; +using SSCMS.Models; +using SSCMS.Utils; +using SSCMS.Wx; + +namespace SSCMS.Core.Services +{ + public partial class WxManager + { + public async Task AddUserTag(string accessTokenOrAppId, string tagName) + { + await UserTagApi.CreateAsync(accessTokenOrAppId, tagName); + } + + public async Task UpdateUserTag(string accessTokenOrAppId, int tagId, string tagName) + { + await UserTagApi.UpdateAsync(accessTokenOrAppId, tagId, tagName); + } + + public async Task DeleteUserTag(string accessTokenOrAppId, int tagId) + { + await UserTagApi.DeleteAsync(accessTokenOrAppId, tagId); + } + + public async Task UpdateUserRemarkAsync(string accessTokenOrAppId, string openId, string remark) + { + await UserApi.UpdateRemarkAsync(accessTokenOrAppId, openId, remark); + } + + public async Task UserBatchTaggingAsync(string accessTokenOrAppId, int tagId, List openIds) + { + await UserTagApi.BatchTaggingAsync(accessTokenOrAppId, tagId, openIds); + } + + public async Task UserBatchUnTaggingAsync(string accessTokenOrAppId, int tagId, List openIds) + { + await UserTagApi.BatchUntaggingAsync(accessTokenOrAppId, tagId, openIds); + } + + public async Task UserBatchBlackListAsync(string accessTokenOrAppId, List openIds) + { + await UserApi.BatchBlackListAsync(accessTokenOrAppId, openIds); + } + + public async Task UserBatchUnBlackListAsync(string accessTokenOrAppId, List openIds) + { + await UserApi.BatchUnBlackListAsync(accessTokenOrAppId, openIds); + } + + public async Task> GetUserTagsAsync(string accessTokenOrAppId) + { + return (await UserTagApi.GetAsync(accessTokenOrAppId)).tags.Select(tag => + new WxUserTag + { + Id = tag.id, + Name = tag.name, + Count = tag.count + }).ToList(); + } + + public async Task> GetUserOpenIdsAsync(string accessTokenOrAppId, bool isBlock) + { + var openIds = new List(); + string nextOpenId = null; + while (true) + { + nextOpenId = await LoadUserOpenIdsAsync(accessTokenOrAppId, openIds, nextOpenId, isBlock); + if (string.IsNullOrEmpty(nextOpenId)) break; + } + + return openIds; + } + + public async Task> GetUsersAsync(string accessTokenOrAppId, List openIds) + { + var users = new List(); + var num = TranslateUtils.Ceiling(openIds.Count, 100); + for (var i = 0; i < num; i++) + { + var pageOpenIds = openIds.Skip(i * 100).Take(100); + + var userList = pageOpenIds.Select(openId => new BatchGetUserInfoData + { + openid = openId, + LangEnum = Language.zh_CN + }) + .ToList(); + var userResult = await UserApi.BatchGetUserInfoAsync(accessTokenOrAppId, userList); + users.AddRange(userResult.user_info_list.Select(GetWxUser)); + } + + users = users.OrderByDescending(x => x.SubscribeTime).ToList(); + + return users; + } + + public async Task GetUserAsync(string accessTokenOrAppId, string openId) + { + if (string.IsNullOrEmpty(openId)) return null; + + var userResult = await UserApi.InfoAsync(accessTokenOrAppId, openId); + + return GetWxUser(userResult); + } + + private async Task LoadUserOpenIdsAsync(string accessTokenOrAppId, List openIds, string nextOpenId, bool isBlock) + { + var openIdResult = isBlock + ? await UserApi.GetBlackListAsync(accessTokenOrAppId, nextOpenId) + : await UserApi.GetAsync(accessTokenOrAppId, nextOpenId); + + if (openIdResult.data != null) + { + openIds.AddRange(openIdResult.data.openid); + } + + return openIds.Count != openIdResult.total ? openIdResult.next_openid : null; + } + + private static WxUser GetWxUser(UserInfoJson json) + { + return new WxUser + { + Subscribe = json.subscribe, + OpenId = json.openid, + Nickname = json.nickname, + Sex = json.sex, + Language = json.language, + City = json.city, + Province = json.province, + Country = json.country, + HeadImgUrl = json.headimgurl, + SubscribeTime = GetDateTimeWithTimeStamp(json.subscribe_time), + UnionId = json.unionid, + Remark = json.remark, + GroupId = json.groupid, + TagIdList = ListUtils.GetIntList(json.tagid_list), + SubscribeScene = json.subscribe_scene, + QrScene = json.qr_scene, + QrSceneStr = json.qr_scene_str + }; + } + + /// + /// 时间戳转换为datetime + /// + /// 微信接口返回时间戳 + /// + private static DateTime GetDateTimeWithTimeStamp(long timeStamp) + { + var startTime = new DateTime(1970, 1, 1); // 当地时区 + return startTime.AddMilliseconds(timeStamp * 1000); + } + } +} diff --git a/src/SSCMS.Core/Services/WxManager.cs b/src/SSCMS.Core/Services/WxManager.cs new file mode 100644 index 000000000..15ba75a4c --- /dev/null +++ b/src/SSCMS.Core/Services/WxManager.cs @@ -0,0 +1,137 @@ +using System; +using System.Threading.Tasks; +using Senparc.Weixin; +using Senparc.Weixin.Exceptions; +using Senparc.Weixin.MP; +using Senparc.Weixin.MP.Containers; +using SSCMS.Core.Utils; +using SSCMS.Enums; +using SSCMS.Repositories; +using SSCMS.Services; +using SSCMS.Utils; + +namespace SSCMS.Core.Services +{ + public partial class WxManager : IWxManager + { + private readonly ISettingsManager _settingsManager; + private readonly IPathManager _pathManager; + private readonly ITaskManager _taskManager; + private readonly IWxAccountRepository _wxAccountRepository; + private readonly IWxMenuRepository _wxMenuRepository; + private readonly IWxChatRepository _wxChatRepository; + private readonly IWxReplyRuleRepository _wxReplyRuleRepository; + private readonly IWxReplyKeywordRepository _wxReplyKeywordRepository; + private readonly IWxReplyMessageRepository _wxReplyMessageRepository; + private readonly IMaterialMessageRepository _materialMessageRepository; + private readonly IMaterialArticleRepository _materialArticleRepository; + private readonly IMaterialImageRepository _materialImageRepository; + private readonly IMaterialAudioRepository _materialAudioRepository; + private readonly IMaterialVideoRepository _materialVideoRepository; + + public WxManager(ISettingsManager settingsManager, IPathManager pathManager, ITaskManager taskManager, IWxAccountRepository wxAccountRepository, + IWxMenuRepository wxMenuRepository, IWxChatRepository wxChatRepository, IWxReplyRuleRepository wxReplyRuleRepository, + IWxReplyKeywordRepository wxReplyKeywordRepository, IWxReplyMessageRepository wxReplyMessageRepository, + IMaterialMessageRepository materialMessageRepository, IMaterialArticleRepository materialArticleRepository, IMaterialImageRepository materialImageRepository, + IMaterialAudioRepository materialAudioRepository, IMaterialVideoRepository materialVideoRepository) + { + _settingsManager = settingsManager; + _pathManager = pathManager; + _taskManager = taskManager; + _wxAccountRepository = wxAccountRepository; + _wxMenuRepository = wxMenuRepository; + _wxChatRepository = wxChatRepository; + _wxReplyRuleRepository = wxReplyRuleRepository; + _wxReplyKeywordRepository = wxReplyKeywordRepository; + _wxReplyMessageRepository = wxReplyMessageRepository; + _materialMessageRepository = materialMessageRepository; + _materialArticleRepository = materialArticleRepository; + _materialImageRepository = materialImageRepository; + _materialAudioRepository = materialAudioRepository; + _materialVideoRepository = materialVideoRepository; + } + + public async Task<(bool, string, string)> GetAccessTokenAsync(int siteId) + { + var account = await _wxAccountRepository.GetBySiteIdAsync(siteId); + if (string.IsNullOrEmpty(account.MpAppId) || string.IsNullOrEmpty(account.MpAppSecret)) + { + return (false, null, "微信公众号AppId及AppSecret未设置,请到平台账号配置中设置"); + } + + return await GetAccessTokenAsync(account.MpAppId, account.MpAppSecret); + } + + public async Task<(bool, string, string)> GetAccessTokenAsync(string mpAppId, string mpAppSecret) + { + var success = false; + var errorMessage = string.Empty; + string token = null; + + try + { + token = await AccessTokenContainer.TryGetAccessTokenAsync(mpAppId, mpAppSecret); + success = true; + } + catch (ErrorJsonResultException ex) + { + if (ex.JsonResult.errcode == ReturnCode.调用接口的IP地址不在白名单中) + { + var startIndex = ex.JsonResult.errmsg.IndexOf("invalid ip ", StringComparison.Ordinal) + 11; + var endIndex = ex.JsonResult.errmsg.IndexOf(" ipv6", StringComparison.Ordinal); + var ip = ex.JsonResult.errmsg.Substring(startIndex, endIndex - startIndex); + errorMessage = $"调用接口的IP地址不在白名单中,请进入微信公众平台,将本服务器的IP地址 {ip} 添加至白名单"; + } + else + { + errorMessage = $"API 调用发生错误:{ex.JsonResult.errmsg}"; + } + } + catch (Exception ex) + { + errorMessage = $"执行过程发生错误:{ex.Message}"; + } + + return (success, token, errorMessage); + } + + private GroupMessageType GetGroupMessageType(MaterialType materialType) + { + if (materialType == MaterialType.Message) return GroupMessageType.mpnews; + if (materialType == MaterialType.Text) return GroupMessageType.text; + if (materialType == MaterialType.Image) return GroupMessageType.image; + if (materialType == MaterialType.Audio) return GroupMessageType.voice; + if (materialType == MaterialType.Video) return GroupMessageType.video; + return GroupMessageType.mpnews; + } + + private string SaveImages(string content) + { + var originalImageSrcs = RegexUtils.GetOriginalImageSrcs(content); + foreach (var originalImageSrc in originalImageSrcs) + { + if (!PageUtils.IsProtocolUrl(originalImageSrc)) continue; + + var extName = "png"; + if (StringUtils.Contains(originalImageSrc, "wx_fmt=")) + { + extName = originalImageSrc.Substring(originalImageSrc.LastIndexOf("=", StringComparison.Ordinal) + 1); + } + + var materialFileName = PathUtils.GetMaterialFileNameByExtName(extName); + var virtualDirectoryPath = PathUtils.GetMaterialVirtualDirectoryPath(UploadType.Image); + + var directoryPath = PathUtils.Combine(_settingsManager.WebRootPath, virtualDirectoryPath); + var filePath = PathUtils.Combine(directoryPath, materialFileName); + + WebClientUtils.Download(originalImageSrc, filePath); + + var imageUrl = PageUtils.Combine(virtualDirectoryPath, materialFileName); + + content = content.Replace(" data-src=", "src="); + content = content.Replace(originalImageSrc, imageUrl); + } + return content; + } + } +} diff --git a/src/SSCMS.Core/StlParser/Model/DynamicInfo.cs b/src/SSCMS.Core/StlParser/Model/DynamicInfo.cs index 6beef8d6f..11873b6cb 100644 --- a/src/SSCMS.Core/StlParser/Model/DynamicInfo.cs +++ b/src/SSCMS.Core/StlParser/Model/DynamicInfo.cs @@ -12,6 +12,11 @@ public partial class DynamicInfo { private ISettingsManager _settingsManager; + public DynamicInfo(ISettingsManager settingsManager) + { + _settingsManager = settingsManager; + } + public static DynamicInfo GetDynamicInfo(ISettingsManager settingsManager, string value, int page, User user, string pathAndQuery) { var dynamicInfo = TranslateUtils.JsonDeserialize(settingsManager.Decrypt(value)); diff --git a/src/SSCMS.Core/StlParser/Model/ListInfo.cs b/src/SSCMS.Core/StlParser/Model/ListInfo.cs index b715f04a2..87f02f7a2 100644 --- a/src/SSCMS.Core/StlParser/Model/ListInfo.cs +++ b/src/SSCMS.Core/StlParser/Model/ListInfo.cs @@ -2,6 +2,7 @@ using System.Collections.Specialized; using System.Text; using System.Threading.Tasks; +using SSCMS.Configuration; using SSCMS.Parse; using SSCMS.Core.StlParser.StlElement; using SSCMS.Core.StlParser.Utility; @@ -220,6 +221,10 @@ public static async Task GetListInfoAsync(IParseManager parseManager, { listInfo.Order = value; } + else if (StringUtils.EqualsIgnoreCase(name, StlListBase.Where)) + { + listInfo.Where = value; + } else if (StringUtils.EqualsIgnoreCase(name, StlListBase.GroupChannel)) { listInfo.GroupChannel = await parseManager.ReplaceStlEntitiesForAttributeValueAsync(value); @@ -363,6 +368,8 @@ public static async Task GetListInfoAsync(IParseManager parseManager, public string Order { get; set; } + public string Where { get; set; } + public string GroupChannel { get; private set; } = string.Empty; public string GroupChannelNot { get; private set; } = string.Empty; diff --git a/src/SSCMS.Core/StlParser/Model/StlAll.cs b/src/SSCMS.Core/StlParser/Model/StlAll.cs index efff01739..687a119e1 100644 --- a/src/SSCMS.Core/StlParser/Model/StlAll.cs +++ b/src/SSCMS.Core/StlParser/Model/StlAll.cs @@ -81,8 +81,8 @@ public static class StlAll typeof(StlItemTemplate) }, { - StlLibrary.ElementName, - typeof(StlLibrary) + StlMaterial.ElementName, + typeof(StlMaterial) }, { StlLoading.ElementName, @@ -164,6 +164,10 @@ public static class StlAll StlTabs.ElementName, typeof(StlTabs) }, + { + StlTags.ElementName, + typeof(StlTags) + }, { StlValue.ElementName, typeof(StlValue) diff --git a/src/SSCMS.Core/StlParser/Model/StlListBase.cs b/src/SSCMS.Core/StlParser/Model/StlListBase.cs index 901477009..ef9df0801 100644 --- a/src/SSCMS.Core/StlParser/Model/StlListBase.cs +++ b/src/SSCMS.Core/StlParser/Model/StlListBase.cs @@ -56,6 +56,9 @@ public class StlListBase [StlAttribute(Title = "排序")] public const string Order = nameof(Order); + [StlAttribute(Title = "条件")] + public const string Where = nameof(Where); + [StlAttribute(Title = "仅显示图片内容")] public const string IsImage = nameof(IsImage); diff --git a/src/SSCMS.Core/StlParser/StlElement/StlA.cs b/src/SSCMS.Core/StlParser/StlElement/StlA.cs index 4ffca6bd8..9f975176a 100644 --- a/src/SSCMS.Core/StlParser/StlElement/StlA.cs +++ b/src/SSCMS.Core/StlParser/StlElement/StlA.cs @@ -151,7 +151,7 @@ private static async Task ParseImplAsync(IParseManager parseManager, str var onclick = string.Empty; if (!string.IsNullOrEmpty(href)) { - url = await parseManager.PathManager.ParseNavigationUrlAsync(pageInfo.Site, href, pageInfo.IsLocal); + url = await parseManager.PathManager.ParseSiteUrlAsync(pageInfo.Site, href, pageInfo.IsLocal); var innerBuilder = new StringBuilder(contextInfo.InnerHtml); await parseManager.ParseInnerContentAsync(innerBuilder); diff --git a/src/SSCMS.Core/StlParser/StlElement/StlAudio.cs b/src/SSCMS.Core/StlParser/StlElement/StlAudio.cs index 51320db01..6fab10799 100644 --- a/src/SSCMS.Core/StlParser/StlElement/StlAudio.cs +++ b/src/SSCMS.Core/StlParser/StlElement/StlAudio.cs @@ -95,27 +95,27 @@ private static async Task ParseImplAsync(IParseManager parseManager, str if (string.IsNullOrEmpty(playUrl)) return string.Empty; - playUrl = await parseManager.PathManager.ParseNavigationUrlAsync(pageInfo.Site, playUrl, pageInfo.IsLocal); + playUrl = await parseManager.PathManager.ParseSiteUrlAsync(pageInfo.Site, playUrl, pageInfo.IsLocal); // 如果是实体标签,则只返回数字 if (contextInfo.IsStlEntity) { return playUrl; } - else - { - await pageInfo.AddPageBodyCodeIfNotExistsAsync(ParsePage.Const.Jquery); - await pageInfo.AddPageBodyCodeIfNotExistsAsync(ParsePage.Const.JsAcMediaElement); - return $@" + await pageInfo.AddPageBodyCodeIfNotExistsAsync(ParsePage.Const.Jquery); + await pageInfo.AddPageBodyCodeIfNotExistsAsync(ParsePage.Const.JsAcMediaElement); + + var url = parseManager.PathManager.GetSiteFilesUrl(Resources.MediaElement.Swf); + + return $@"