Skip to content

Commit 3459aee

Browse files
committed
Move credentials and options to json config file so that driver/example program can be
published to public repositories i.e., github In doing so, - provide a list of patterns in config so that internal / confidential strings can be put there - add namespace 'WPExportApp' to share it with JsonConfig class - add unicode examples: weird char replacements And, - comment 'CustomMetadata' out, for actual applications // Initial PR Date: 11-21-2021
1 parent f6888d9 commit 3459aee

3 files changed

Lines changed: 172 additions & 33 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
namespace WPExportApp {
2+
using System;
3+
using System.Threading.Tasks;
4+
5+
/// <summary>
6+
/// Credentials Related
7+
/// Provides
8+
/// - Credentials
9+
/// - Additional options i.e., for SSL
10+
/// - Patterns for substitution/pre-processing content
11+
/// </summary>
12+
class JsonConfig {
13+
public WPExpJsonConfig? Options { get; set; }
14+
15+
/// <summary>
16+
/// Config file path
17+
/// </summary>
18+
private string JsonConfigFilePath { get; set; }
19+
20+
/// <remarks>
21+
/// <see href="https://docs.microsoft.com/en-us/dotnet/api/system.environment.specialfolder">
22+
/// Accessing Local App Data via Environment
23+
/// </see>
24+
/// </remarks>
25+
public JsonConfig() {
26+
JsonConfigFilePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
27+
+ @"\WPExportConfig.json";
28+
29+
if (!System.IO.File.Exists(JsonConfigFilePath)) {
30+
throw new InvalidOperationException($"Required config: {JsonConfigFilePath} not found!" +
31+
"Please create the config file and run this application again.");
32+
}
33+
}
34+
35+
public class ReplacePattern {
36+
public string Needle { get; set; }
37+
public string Substitute { get; set; }
38+
}
39+
40+
/// <summary>
41+
/// Structure to read records from config file (json format)
42+
/// Self explanatory props
43+
/// </summary>
44+
public class WPExpJsonConfig {
45+
public string Host { get; set; }
46+
public string Database { get; set; }
47+
public string Username { get; set; }
48+
public string Password { get; set; }
49+
public string TlsVersion { get; set; }
50+
public string ContentOutputDirectory { get; set; }
51+
public string ArchiveOutputFilePath { get; set; }
52+
/// <summary>
53+
/// Some of the patterns might be internal only and should not be published online
54+
/// Therefore, it might be good idea to keep them in the json config file.
55+
/// </summary>
56+
public ReplacePattern[] Patterns { get; set; }
57+
}
58+
59+
60+
/// <summary>
61+
/// Read and Parse Config file
62+
/// </summary>
63+
public async Task Load() {
64+
using System.IO.FileStream openStream = System.IO.File.OpenRead(JsonConfigFilePath);
65+
Options = await System.Text.Json.JsonSerializer.DeserializeAsync<WPExpJsonConfig>(openStream);
66+
67+
if (Options == null || string.IsNullOrEmpty(Options.Host) || string.IsNullOrEmpty(
68+
Options.Database) || string.IsNullOrEmpty(Options.Username) || string.IsNullOrEmpty(
69+
Options.Password)) {
70+
throw new NullReferenceException("Database Credentials are empty in Json config file!");
71+
}
72+
}
73+
}
74+
}
Lines changed: 74 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,82 @@
1-
using Goodbye.WordPress;
1+
namespace WPExportApp {
2+
using System.Threading.Tasks;
3+
using Goodbye.WordPress;
24

3-
var exporter = WordPressExporter.Create(
4-
postReader: new MysqlPostReader(new ConnectionStringBuilder
5+
class WPExportMain {
6+
/// <summary>
7+
/// Entry Point
8+
/// </summary>
9+
/// <param name="args">CLA</param>
10+
static async Task Main(string[] args)
11+
{
12+
var config = new JsonConfig();
13+
await config.Load();
14+
if (config.Options == null)
15+
throw new System.NullReferenceException();
16+
17+
var exporter = WordPressExporter.Create(
18+
postReader: new MysqlPostReader(
19+
new ConnectionStringBuilder {
20+
Host = config.Options.Host,
21+
Database = config.Options.Database,
22+
Username = config.Options.Username,
23+
Password = config.Options.Password
24+
// , TlsVersion = config.Options.TlsVersion
25+
}),
26+
contentOutputDirectory: config.Options.ContentOutputDirectory,
27+
archiveOutputFilePath: config.Options.ArchiveOutputFilePath,
28+
// And now the delegate...
29+
@delegate: new CustomExporterDelegate(config.Options.Patterns)
30+
);
31+
32+
await exporter.ExportAsync();
33+
}
34+
}
35+
36+
37+
sealed class CustomExporterDelegate : WordPressExporterDelegate
538
{
6-
Host = "localhost",
7-
Username = "user",
8-
Password = "***",
9-
Database = "wordpressdb"
10-
}),
11-
contentOutputDirectory: "exported-posts",
12-
archiveOutputFilePath: "exported-posts/archive.json",
13-
14-
// And now the delegate...
15-
@delegate: new CustomExporterDelegate());
16-
17-
await exporter.ExportAsync();
18-
19-
sealed class CustomExporterDelegate : WordPressExporterDelegate
20-
{
21-
/// <summary>Process post contents</summary>
22-
public override Post ProcessPost(
23-
WordPressExporter exporter,
24-
Post post)
39+
JsonConfig.ReplacePattern[] StrPatterns;
40+
41+
public CustomExporterDelegate(JsonConfig.ReplacePattern[] patterns)
42+
{
43+
StrPatterns = patterns;
44+
}
45+
46+
// Replace weird unicode chars
47+
private string SubstituteCommon(string str) =>
48+
str.Replace("‘", "'").Replace("’", "'")
49+
.Replace("“", "\"").Replace("”", "\"");
50+
51+
private string ProcessContent(string content) {
52+
content = SubstituteCommon(content)
53+
.Replace("http://", "https://");
54+
55+
if (StrPatterns != null && StrPatterns.Length > 0)
56+
foreach( var pattern in StrPatterns)
57+
content = content.Replace(pattern.Needle, pattern.Substitute);
58+
59+
return content;
60+
}
61+
62+
/// <summary>Process post contents</summary>
63+
public override Post ProcessPost(
64+
WordPressExporter exporter,
65+
Post post)
2566
// Perform the default post processing first by calling base
2667
=> base.ProcessPost(exporter, post) with
2768
{
28-
// Then replace '--' with Unicode em dash '—'
29-
Content = post.Content.Replace("--", "—")
69+
Content = ProcessContent(post.Content)
3070
};
3171

32-
/// <summary>Add 'CustomMetadata' to each post's YAML front matter</summary>
33-
public override void PopulatePostYamlFrontMatter(
34-
WordPressExporter exporter,
35-
Post post,
36-
SharpYaml.Serialization.YamlMappingNode rootNode)
37-
{
38-
base.PopulatePostYamlFrontMatter(exporter, post, rootNode);
39-
rootNode.Add("CustomMetadata", "Some Value");
72+
/// <summary>Add 'CustomMetadata' to each post's YAML front matter</summary>
73+
public override void PopulatePostYamlFrontMatter(
74+
WordPressExporter exporter,
75+
Post post,
76+
SharpYaml.Serialization.YamlMappingNode rootNode)
77+
{
78+
base.PopulatePostYamlFrontMatter(exporter, post, rootNode);
79+
// rootNode.Add("CustomMetadata", "Some Value");
80+
}
4081
}
41-
}
82+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## Example Json Config
2+
Default config path: "$Env:LocalAppData\WPExportConfig.json"
3+
4+
For example, `C:\Users\UserName\AppData\Local\WPExportConfig.json`
5+
6+
An example config looks like following,
7+
8+
{
9+
"Host": "localhost",
10+
"Username": "user",
11+
"Password": "your_password",
12+
"Database": "wordpress_db_name",
13+
"ContentOutputDirectory": "posts",
14+
"ArchiveOutputFilePath": "posts/archive.json",
15+
"Patterns": [
16+
{
17+
"Needle": "old-domain.com",
18+
"Substitute": "new-domain.com"
19+
}
20+
]
21+
}
22+
23+
24+
For example without json config, please have a look at [primary ReadMe](https://github.com/abock/goodbye-wordpress#example-programcs).

0 commit comments

Comments
 (0)