Skip to content

Commit 8dfe2c3

Browse files
committed
Move credentials and options to json config file so that driver 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
1 parent 0570aca commit 8dfe2c3

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)